/*
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [http://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.neo4j.gds.core.compression.packed;

import org.neo4j.internal.unsafe.UnsafeUtil;

import org.neo4j.gds.mem.BitUtil;

/**
 * This class is generated by src/main.rs
 * Do not edit this file directly.
 */
public final class AdjacencyUnpacking {

    private AdjacencyUnpacking() {
    }

    public static final int BLOCK_SIZE = 64;

    public static int advanceValueOffset(int valuesStart) {
        return valuesStart + BLOCK_SIZE;
    }

    public static long unpack(int bits, long[] values, int valuesStart, long packedPtr) {
        assert bits <= 64 : "Bits must be at most 64 but was " + bits;
        return UNPACKERS[bits].unpack(values, valuesStart, packedPtr);
    }

    @FunctionalInterface
    private interface Unpacker {

        long unpack(long[] values, int valuesStart, long packedPtr);
    }

    private static final Unpacker[] UNPACKERS = {
        AdjacencyUnpacking::unpack0,
        AdjacencyUnpacking::unpack1,
        AdjacencyUnpacking::unpack2,
        AdjacencyUnpacking::unpack3,
        AdjacencyUnpacking::unpack4,
        AdjacencyUnpacking::unpack5,
        AdjacencyUnpacking::unpack6,
        AdjacencyUnpacking::unpack7,
        AdjacencyUnpacking::unpack8,
        AdjacencyUnpacking::unpack9,
        AdjacencyUnpacking::unpack10,
        AdjacencyUnpacking::unpack11,
        AdjacencyUnpacking::unpack12,
        AdjacencyUnpacking::unpack13,
        AdjacencyUnpacking::unpack14,
        AdjacencyUnpacking::unpack15,
        AdjacencyUnpacking::unpack16,
        AdjacencyUnpacking::unpack17,
        AdjacencyUnpacking::unpack18,
        AdjacencyUnpacking::unpack19,
        AdjacencyUnpacking::unpack20,
        AdjacencyUnpacking::unpack21,
        AdjacencyUnpacking::unpack22,
        AdjacencyUnpacking::unpack23,
        AdjacencyUnpacking::unpack24,
        AdjacencyUnpacking::unpack25,
        AdjacencyUnpacking::unpack26,
        AdjacencyUnpacking::unpack27,
        AdjacencyUnpacking::unpack28,
        AdjacencyUnpacking::unpack29,
        AdjacencyUnpacking::unpack30,
        AdjacencyUnpacking::unpack31,
        AdjacencyUnpacking::unpack32,
        AdjacencyUnpacking::unpack33,
        AdjacencyUnpacking::unpack34,
        AdjacencyUnpacking::unpack35,
        AdjacencyUnpacking::unpack36,
        AdjacencyUnpacking::unpack37,
        AdjacencyUnpacking::unpack38,
        AdjacencyUnpacking::unpack39,
        AdjacencyUnpacking::unpack40,
        AdjacencyUnpacking::unpack41,
        AdjacencyUnpacking::unpack42,
        AdjacencyUnpacking::unpack43,
        AdjacencyUnpacking::unpack44,
        AdjacencyUnpacking::unpack45,
        AdjacencyUnpacking::unpack46,
        AdjacencyUnpacking::unpack47,
        AdjacencyUnpacking::unpack48,
        AdjacencyUnpacking::unpack49,
        AdjacencyUnpacking::unpack50,
        AdjacencyUnpacking::unpack51,
        AdjacencyUnpacking::unpack52,
        AdjacencyUnpacking::unpack53,
        AdjacencyUnpacking::unpack54,
        AdjacencyUnpacking::unpack55,
        AdjacencyUnpacking::unpack56,
        AdjacencyUnpacking::unpack57,
        AdjacencyUnpacking::unpack58,
        AdjacencyUnpacking::unpack59,
        AdjacencyUnpacking::unpack60,
        AdjacencyUnpacking::unpack61,
        AdjacencyUnpacking::unpack62,
        AdjacencyUnpacking::unpack63,
        AdjacencyUnpacking::unpack64,
    };

    public static long loopUnpack(int bits, long[] values, int valuesStart, int valuesLength, long packedPtr) {
        assert bits <= 64 : "Bits must be at most 64 but was " + bits;
        return LOOP_UNPACKERS[bits].loopUnpack(values, valuesStart, valuesLength, packedPtr);
    }

    @FunctionalInterface
    private interface LoopUnpacker {

        long loopUnpack(long[] values, int valuesStart, int valuesLength, long packedPtr);
    }

    private static final LoopUnpacker[] LOOP_UNPACKERS = {
        AdjacencyUnpacking::unpackLoop0,
        AdjacencyUnpacking::unpackLoop1,
        AdjacencyUnpacking::unpackLoop2,
        AdjacencyUnpacking::unpackLoop3,
        AdjacencyUnpacking::unpackLoop4,
        AdjacencyUnpacking::unpackLoop5,
        AdjacencyUnpacking::unpackLoop6,
        AdjacencyUnpacking::unpackLoop7,
        AdjacencyUnpacking::unpackLoop8,
        AdjacencyUnpacking::unpackLoop9,
        AdjacencyUnpacking::unpackLoop10,
        AdjacencyUnpacking::unpackLoop11,
        AdjacencyUnpacking::unpackLoop12,
        AdjacencyUnpacking::unpackLoop13,
        AdjacencyUnpacking::unpackLoop14,
        AdjacencyUnpacking::unpackLoop15,
        AdjacencyUnpacking::unpackLoop16,
        AdjacencyUnpacking::unpackLoop17,
        AdjacencyUnpacking::unpackLoop18,
        AdjacencyUnpacking::unpackLoop19,
        AdjacencyUnpacking::unpackLoop20,
        AdjacencyUnpacking::unpackLoop21,
        AdjacencyUnpacking::unpackLoop22,
        AdjacencyUnpacking::unpackLoop23,
        AdjacencyUnpacking::unpackLoop24,
        AdjacencyUnpacking::unpackLoop25,
        AdjacencyUnpacking::unpackLoop26,
        AdjacencyUnpacking::unpackLoop27,
        AdjacencyUnpacking::unpackLoop28,
        AdjacencyUnpacking::unpackLoop29,
        AdjacencyUnpacking::unpackLoop30,
        AdjacencyUnpacking::unpackLoop31,
        AdjacencyUnpacking::unpackLoop32,
        AdjacencyUnpacking::unpackLoop33,
        AdjacencyUnpacking::unpackLoop34,
        AdjacencyUnpacking::unpackLoop35,
        AdjacencyUnpacking::unpackLoop36,
        AdjacencyUnpacking::unpackLoop37,
        AdjacencyUnpacking::unpackLoop38,
        AdjacencyUnpacking::unpackLoop39,
        AdjacencyUnpacking::unpackLoop40,
        AdjacencyUnpacking::unpackLoop41,
        AdjacencyUnpacking::unpackLoop42,
        AdjacencyUnpacking::unpackLoop43,
        AdjacencyUnpacking::unpackLoop44,
        AdjacencyUnpacking::unpackLoop45,
        AdjacencyUnpacking::unpackLoop46,
        AdjacencyUnpacking::unpackLoop47,
        AdjacencyUnpacking::unpackLoop48,
        AdjacencyUnpacking::unpackLoop49,
        AdjacencyUnpacking::unpackLoop50,
        AdjacencyUnpacking::unpackLoop51,
        AdjacencyUnpacking::unpackLoop52,
        AdjacencyUnpacking::unpackLoop53,
        AdjacencyUnpacking::unpackLoop54,
        AdjacencyUnpacking::unpackLoop55,
        AdjacencyUnpacking::unpackLoop56,
        AdjacencyUnpacking::unpackLoop57,
        AdjacencyUnpacking::unpackLoop58,
        AdjacencyUnpacking::unpackLoop59,
        AdjacencyUnpacking::unpackLoop60,
        AdjacencyUnpacking::unpackLoop61,
        AdjacencyUnpacking::unpackLoop62,
        AdjacencyUnpacking::unpackLoop63,
        AdjacencyUnpacking::unpackLoop64,
    };

    /**
     * Unpacks 64 0-bit values using 0 bytes, touching 0 words.
     */
    private static long unpack0(long[] values, int valuesStart, long packedPtr) {
        java.util.Arrays.fill(values, valuesStart, valuesStart + 64, 0x0L);
        return packedPtr;
    }

    /**
     * Unpacks 64 1-bit values using 8 bytes, touching 1 word.
     */
    private static long unpack1(long[] values, int valuesStart, long packedPtr) {
        // Access 1 word
        long w0 = UnsafeUtil.getLong(packedPtr);
        values[valuesStart] = w0 & 0x1L;
        values[1 + valuesStart] = w0 >>> 1 & 0x1L;
        values[2 + valuesStart] = w0 >>> 2 & 0x1L;
        values[3 + valuesStart] = w0 >>> 3 & 0x1L;
        values[4 + valuesStart] = w0 >>> 4 & 0x1L;
        values[5 + valuesStart] = w0 >>> 5 & 0x1L;
        values[6 + valuesStart] = w0 >>> 6 & 0x1L;
        values[7 + valuesStart] = w0 >>> 7 & 0x1L;
        values[8 + valuesStart] = w0 >>> 8 & 0x1L;
        values[9 + valuesStart] = w0 >>> 9 & 0x1L;
        values[10 + valuesStart] = w0 >>> 10 & 0x1L;
        values[11 + valuesStart] = w0 >>> 11 & 0x1L;
        values[12 + valuesStart] = w0 >>> 12 & 0x1L;
        values[13 + valuesStart] = w0 >>> 13 & 0x1L;
        values[14 + valuesStart] = w0 >>> 14 & 0x1L;
        values[15 + valuesStart] = w0 >>> 15 & 0x1L;
        values[16 + valuesStart] = w0 >>> 16 & 0x1L;
        values[17 + valuesStart] = w0 >>> 17 & 0x1L;
        values[18 + valuesStart] = w0 >>> 18 & 0x1L;
        values[19 + valuesStart] = w0 >>> 19 & 0x1L;
        values[20 + valuesStart] = w0 >>> 20 & 0x1L;
        values[21 + valuesStart] = w0 >>> 21 & 0x1L;
        values[22 + valuesStart] = w0 >>> 22 & 0x1L;
        values[23 + valuesStart] = w0 >>> 23 & 0x1L;
        values[24 + valuesStart] = w0 >>> 24 & 0x1L;
        values[25 + valuesStart] = w0 >>> 25 & 0x1L;
        values[26 + valuesStart] = w0 >>> 26 & 0x1L;
        values[27 + valuesStart] = w0 >>> 27 & 0x1L;
        values[28 + valuesStart] = w0 >>> 28 & 0x1L;
        values[29 + valuesStart] = w0 >>> 29 & 0x1L;
        values[30 + valuesStart] = w0 >>> 30 & 0x1L;
        values[31 + valuesStart] = w0 >>> 31 & 0x1L;
        values[32 + valuesStart] = w0 >>> 32 & 0x1L;
        values[33 + valuesStart] = w0 >>> 33 & 0x1L;
        values[34 + valuesStart] = w0 >>> 34 & 0x1L;
        values[35 + valuesStart] = w0 >>> 35 & 0x1L;
        values[36 + valuesStart] = w0 >>> 36 & 0x1L;
        values[37 + valuesStart] = w0 >>> 37 & 0x1L;
        values[38 + valuesStart] = w0 >>> 38 & 0x1L;
        values[39 + valuesStart] = w0 >>> 39 & 0x1L;
        values[40 + valuesStart] = w0 >>> 40 & 0x1L;
        values[41 + valuesStart] = w0 >>> 41 & 0x1L;
        values[42 + valuesStart] = w0 >>> 42 & 0x1L;
        values[43 + valuesStart] = w0 >>> 43 & 0x1L;
        values[44 + valuesStart] = w0 >>> 44 & 0x1L;
        values[45 + valuesStart] = w0 >>> 45 & 0x1L;
        values[46 + valuesStart] = w0 >>> 46 & 0x1L;
        values[47 + valuesStart] = w0 >>> 47 & 0x1L;
        values[48 + valuesStart] = w0 >>> 48 & 0x1L;
        values[49 + valuesStart] = w0 >>> 49 & 0x1L;
        values[50 + valuesStart] = w0 >>> 50 & 0x1L;
        values[51 + valuesStart] = w0 >>> 51 & 0x1L;
        values[52 + valuesStart] = w0 >>> 52 & 0x1L;
        values[53 + valuesStart] = w0 >>> 53 & 0x1L;
        values[54 + valuesStart] = w0 >>> 54 & 0x1L;
        values[55 + valuesStart] = w0 >>> 55 & 0x1L;
        values[56 + valuesStart] = w0 >>> 56 & 0x1L;
        values[57 + valuesStart] = w0 >>> 57 & 0x1L;
        values[58 + valuesStart] = w0 >>> 58 & 0x1L;
        values[59 + valuesStart] = w0 >>> 59 & 0x1L;
        values[60 + valuesStart] = w0 >>> 60 & 0x1L;
        values[61 + valuesStart] = w0 >>> 61 & 0x1L;
        values[62 + valuesStart] = w0 >>> 62 & 0x1L;
        values[63 + valuesStart] = w0 >>> 63;
        return 8 + packedPtr;
    }

    /**
     * Unpacks 64 2-bit values using 16 bytes, touching 2 words.
     */
    private static long unpack2(long[] values, int valuesStart, long packedPtr) {
        // Access 2 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        values[valuesStart] = w0 & 0x3L;
        values[1 + valuesStart] = w0 >>> 2 & 0x3L;
        values[2 + valuesStart] = w0 >>> 4 & 0x3L;
        values[3 + valuesStart] = w0 >>> 6 & 0x3L;
        values[4 + valuesStart] = w0 >>> 8 & 0x3L;
        values[5 + valuesStart] = w0 >>> 10 & 0x3L;
        values[6 + valuesStart] = w0 >>> 12 & 0x3L;
        values[7 + valuesStart] = w0 >>> 14 & 0x3L;
        values[8 + valuesStart] = w0 >>> 16 & 0x3L;
        values[9 + valuesStart] = w0 >>> 18 & 0x3L;
        values[10 + valuesStart] = w0 >>> 20 & 0x3L;
        values[11 + valuesStart] = w0 >>> 22 & 0x3L;
        values[12 + valuesStart] = w0 >>> 24 & 0x3L;
        values[13 + valuesStart] = w0 >>> 26 & 0x3L;
        values[14 + valuesStart] = w0 >>> 28 & 0x3L;
        values[15 + valuesStart] = w0 >>> 30 & 0x3L;
        values[16 + valuesStart] = w0 >>> 32 & 0x3L;
        values[17 + valuesStart] = w0 >>> 34 & 0x3L;
        values[18 + valuesStart] = w0 >>> 36 & 0x3L;
        values[19 + valuesStart] = w0 >>> 38 & 0x3L;
        values[20 + valuesStart] = w0 >>> 40 & 0x3L;
        values[21 + valuesStart] = w0 >>> 42 & 0x3L;
        values[22 + valuesStart] = w0 >>> 44 & 0x3L;
        values[23 + valuesStart] = w0 >>> 46 & 0x3L;
        values[24 + valuesStart] = w0 >>> 48 & 0x3L;
        values[25 + valuesStart] = w0 >>> 50 & 0x3L;
        values[26 + valuesStart] = w0 >>> 52 & 0x3L;
        values[27 + valuesStart] = w0 >>> 54 & 0x3L;
        values[28 + valuesStart] = w0 >>> 56 & 0x3L;
        values[29 + valuesStart] = w0 >>> 58 & 0x3L;
        values[30 + valuesStart] = w0 >>> 60 & 0x3L;
        values[31 + valuesStart] = w0 >>> 62;
        values[32 + valuesStart] = w1 & 0x3L;
        values[33 + valuesStart] = w1 >>> 2 & 0x3L;
        values[34 + valuesStart] = w1 >>> 4 & 0x3L;
        values[35 + valuesStart] = w1 >>> 6 & 0x3L;
        values[36 + valuesStart] = w1 >>> 8 & 0x3L;
        values[37 + valuesStart] = w1 >>> 10 & 0x3L;
        values[38 + valuesStart] = w1 >>> 12 & 0x3L;
        values[39 + valuesStart] = w1 >>> 14 & 0x3L;
        values[40 + valuesStart] = w1 >>> 16 & 0x3L;
        values[41 + valuesStart] = w1 >>> 18 & 0x3L;
        values[42 + valuesStart] = w1 >>> 20 & 0x3L;
        values[43 + valuesStart] = w1 >>> 22 & 0x3L;
        values[44 + valuesStart] = w1 >>> 24 & 0x3L;
        values[45 + valuesStart] = w1 >>> 26 & 0x3L;
        values[46 + valuesStart] = w1 >>> 28 & 0x3L;
        values[47 + valuesStart] = w1 >>> 30 & 0x3L;
        values[48 + valuesStart] = w1 >>> 32 & 0x3L;
        values[49 + valuesStart] = w1 >>> 34 & 0x3L;
        values[50 + valuesStart] = w1 >>> 36 & 0x3L;
        values[51 + valuesStart] = w1 >>> 38 & 0x3L;
        values[52 + valuesStart] = w1 >>> 40 & 0x3L;
        values[53 + valuesStart] = w1 >>> 42 & 0x3L;
        values[54 + valuesStart] = w1 >>> 44 & 0x3L;
        values[55 + valuesStart] = w1 >>> 46 & 0x3L;
        values[56 + valuesStart] = w1 >>> 48 & 0x3L;
        values[57 + valuesStart] = w1 >>> 50 & 0x3L;
        values[58 + valuesStart] = w1 >>> 52 & 0x3L;
        values[59 + valuesStart] = w1 >>> 54 & 0x3L;
        values[60 + valuesStart] = w1 >>> 56 & 0x3L;
        values[61 + valuesStart] = w1 >>> 58 & 0x3L;
        values[62 + valuesStart] = w1 >>> 60 & 0x3L;
        values[63 + valuesStart] = w1 >>> 62;
        return 16 + packedPtr;
    }

    /**
     * Unpacks 64 3-bit values using 24 bytes, touching 3 words.
     */
    private static long unpack3(long[] values, int valuesStart, long packedPtr) {
        // Access 3 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        values[valuesStart] = w0 & 0x7L;
        values[1 + valuesStart] = w0 >>> 3 & 0x7L;
        values[2 + valuesStart] = w0 >>> 6 & 0x7L;
        values[3 + valuesStart] = w0 >>> 9 & 0x7L;
        values[4 + valuesStart] = w0 >>> 12 & 0x7L;
        values[5 + valuesStart] = w0 >>> 15 & 0x7L;
        values[6 + valuesStart] = w0 >>> 18 & 0x7L;
        values[7 + valuesStart] = w0 >>> 21 & 0x7L;
        values[8 + valuesStart] = w0 >>> 24 & 0x7L;
        values[9 + valuesStart] = w0 >>> 27 & 0x7L;
        values[10 + valuesStart] = w0 >>> 30 & 0x7L;
        values[11 + valuesStart] = w0 >>> 33 & 0x7L;
        values[12 + valuesStart] = w0 >>> 36 & 0x7L;
        values[13 + valuesStart] = w0 >>> 39 & 0x7L;
        values[14 + valuesStart] = w0 >>> 42 & 0x7L;
        values[15 + valuesStart] = w0 >>> 45 & 0x7L;
        values[16 + valuesStart] = w0 >>> 48 & 0x7L;
        values[17 + valuesStart] = w0 >>> 51 & 0x7L;
        values[18 + valuesStart] = w0 >>> 54 & 0x7L;
        values[19 + valuesStart] = w0 >>> 57 & 0x7L;
        values[20 + valuesStart] = w0 >>> 60 & 0x7L;
        values[21 + valuesStart] = (w0 >>> 63 | w1 << 1) & 0x7L;
        values[22 + valuesStart] = w1 >>> 2 & 0x7L;
        values[23 + valuesStart] = w1 >>> 5 & 0x7L;
        values[24 + valuesStart] = w1 >>> 8 & 0x7L;
        values[25 + valuesStart] = w1 >>> 11 & 0x7L;
        values[26 + valuesStart] = w1 >>> 14 & 0x7L;
        values[27 + valuesStart] = w1 >>> 17 & 0x7L;
        values[28 + valuesStart] = w1 >>> 20 & 0x7L;
        values[29 + valuesStart] = w1 >>> 23 & 0x7L;
        values[30 + valuesStart] = w1 >>> 26 & 0x7L;
        values[31 + valuesStart] = w1 >>> 29 & 0x7L;
        values[32 + valuesStart] = w1 >>> 32 & 0x7L;
        values[33 + valuesStart] = w1 >>> 35 & 0x7L;
        values[34 + valuesStart] = w1 >>> 38 & 0x7L;
        values[35 + valuesStart] = w1 >>> 41 & 0x7L;
        values[36 + valuesStart] = w1 >>> 44 & 0x7L;
        values[37 + valuesStart] = w1 >>> 47 & 0x7L;
        values[38 + valuesStart] = w1 >>> 50 & 0x7L;
        values[39 + valuesStart] = w1 >>> 53 & 0x7L;
        values[40 + valuesStart] = w1 >>> 56 & 0x7L;
        values[41 + valuesStart] = w1 >>> 59 & 0x7L;
        values[42 + valuesStart] = (w1 >>> 62 | w2 << 2) & 0x7L;
        values[43 + valuesStart] = w2 >>> 1 & 0x7L;
        values[44 + valuesStart] = w2 >>> 4 & 0x7L;
        values[45 + valuesStart] = w2 >>> 7 & 0x7L;
        values[46 + valuesStart] = w2 >>> 10 & 0x7L;
        values[47 + valuesStart] = w2 >>> 13 & 0x7L;
        values[48 + valuesStart] = w2 >>> 16 & 0x7L;
        values[49 + valuesStart] = w2 >>> 19 & 0x7L;
        values[50 + valuesStart] = w2 >>> 22 & 0x7L;
        values[51 + valuesStart] = w2 >>> 25 & 0x7L;
        values[52 + valuesStart] = w2 >>> 28 & 0x7L;
        values[53 + valuesStart] = w2 >>> 31 & 0x7L;
        values[54 + valuesStart] = w2 >>> 34 & 0x7L;
        values[55 + valuesStart] = w2 >>> 37 & 0x7L;
        values[56 + valuesStart] = w2 >>> 40 & 0x7L;
        values[57 + valuesStart] = w2 >>> 43 & 0x7L;
        values[58 + valuesStart] = w2 >>> 46 & 0x7L;
        values[59 + valuesStart] = w2 >>> 49 & 0x7L;
        values[60 + valuesStart] = w2 >>> 52 & 0x7L;
        values[61 + valuesStart] = w2 >>> 55 & 0x7L;
        values[62 + valuesStart] = w2 >>> 58 & 0x7L;
        values[63 + valuesStart] = w2 >>> 61;
        return 24 + packedPtr;
    }

    /**
     * Unpacks 64 4-bit values using 32 bytes, touching 4 words.
     */
    private static long unpack4(long[] values, int valuesStart, long packedPtr) {
        // Access 4 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        values[valuesStart] = w0 & 0xFL;
        values[1 + valuesStart] = w0 >>> 4 & 0xFL;
        values[2 + valuesStart] = w0 >>> 8 & 0xFL;
        values[3 + valuesStart] = w0 >>> 12 & 0xFL;
        values[4 + valuesStart] = w0 >>> 16 & 0xFL;
        values[5 + valuesStart] = w0 >>> 20 & 0xFL;
        values[6 + valuesStart] = w0 >>> 24 & 0xFL;
        values[7 + valuesStart] = w0 >>> 28 & 0xFL;
        values[8 + valuesStart] = w0 >>> 32 & 0xFL;
        values[9 + valuesStart] = w0 >>> 36 & 0xFL;
        values[10 + valuesStart] = w0 >>> 40 & 0xFL;
        values[11 + valuesStart] = w0 >>> 44 & 0xFL;
        values[12 + valuesStart] = w0 >>> 48 & 0xFL;
        values[13 + valuesStart] = w0 >>> 52 & 0xFL;
        values[14 + valuesStart] = w0 >>> 56 & 0xFL;
        values[15 + valuesStart] = w0 >>> 60;
        values[16 + valuesStart] = w1 & 0xFL;
        values[17 + valuesStart] = w1 >>> 4 & 0xFL;
        values[18 + valuesStart] = w1 >>> 8 & 0xFL;
        values[19 + valuesStart] = w1 >>> 12 & 0xFL;
        values[20 + valuesStart] = w1 >>> 16 & 0xFL;
        values[21 + valuesStart] = w1 >>> 20 & 0xFL;
        values[22 + valuesStart] = w1 >>> 24 & 0xFL;
        values[23 + valuesStart] = w1 >>> 28 & 0xFL;
        values[24 + valuesStart] = w1 >>> 32 & 0xFL;
        values[25 + valuesStart] = w1 >>> 36 & 0xFL;
        values[26 + valuesStart] = w1 >>> 40 & 0xFL;
        values[27 + valuesStart] = w1 >>> 44 & 0xFL;
        values[28 + valuesStart] = w1 >>> 48 & 0xFL;
        values[29 + valuesStart] = w1 >>> 52 & 0xFL;
        values[30 + valuesStart] = w1 >>> 56 & 0xFL;
        values[31 + valuesStart] = w1 >>> 60;
        values[32 + valuesStart] = w2 & 0xFL;
        values[33 + valuesStart] = w2 >>> 4 & 0xFL;
        values[34 + valuesStart] = w2 >>> 8 & 0xFL;
        values[35 + valuesStart] = w2 >>> 12 & 0xFL;
        values[36 + valuesStart] = w2 >>> 16 & 0xFL;
        values[37 + valuesStart] = w2 >>> 20 & 0xFL;
        values[38 + valuesStart] = w2 >>> 24 & 0xFL;
        values[39 + valuesStart] = w2 >>> 28 & 0xFL;
        values[40 + valuesStart] = w2 >>> 32 & 0xFL;
        values[41 + valuesStart] = w2 >>> 36 & 0xFL;
        values[42 + valuesStart] = w2 >>> 40 & 0xFL;
        values[43 + valuesStart] = w2 >>> 44 & 0xFL;
        values[44 + valuesStart] = w2 >>> 48 & 0xFL;
        values[45 + valuesStart] = w2 >>> 52 & 0xFL;
        values[46 + valuesStart] = w2 >>> 56 & 0xFL;
        values[47 + valuesStart] = w2 >>> 60;
        values[48 + valuesStart] = w3 & 0xFL;
        values[49 + valuesStart] = w3 >>> 4 & 0xFL;
        values[50 + valuesStart] = w3 >>> 8 & 0xFL;
        values[51 + valuesStart] = w3 >>> 12 & 0xFL;
        values[52 + valuesStart] = w3 >>> 16 & 0xFL;
        values[53 + valuesStart] = w3 >>> 20 & 0xFL;
        values[54 + valuesStart] = w3 >>> 24 & 0xFL;
        values[55 + valuesStart] = w3 >>> 28 & 0xFL;
        values[56 + valuesStart] = w3 >>> 32 & 0xFL;
        values[57 + valuesStart] = w3 >>> 36 & 0xFL;
        values[58 + valuesStart] = w3 >>> 40 & 0xFL;
        values[59 + valuesStart] = w3 >>> 44 & 0xFL;
        values[60 + valuesStart] = w3 >>> 48 & 0xFL;
        values[61 + valuesStart] = w3 >>> 52 & 0xFL;
        values[62 + valuesStart] = w3 >>> 56 & 0xFL;
        values[63 + valuesStart] = w3 >>> 60;
        return 32 + packedPtr;
    }

    /**
     * Unpacks 64 5-bit values using 40 bytes, touching 5 words.
     */
    private static long unpack5(long[] values, int valuesStart, long packedPtr) {
        // Access 5 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        values[valuesStart] = w0 & 0x1FL;
        values[1 + valuesStart] = w0 >>> 5 & 0x1FL;
        values[2 + valuesStart] = w0 >>> 10 & 0x1FL;
        values[3 + valuesStart] = w0 >>> 15 & 0x1FL;
        values[4 + valuesStart] = w0 >>> 20 & 0x1FL;
        values[5 + valuesStart] = w0 >>> 25 & 0x1FL;
        values[6 + valuesStart] = w0 >>> 30 & 0x1FL;
        values[7 + valuesStart] = w0 >>> 35 & 0x1FL;
        values[8 + valuesStart] = w0 >>> 40 & 0x1FL;
        values[9 + valuesStart] = w0 >>> 45 & 0x1FL;
        values[10 + valuesStart] = w0 >>> 50 & 0x1FL;
        values[11 + valuesStart] = w0 >>> 55 & 0x1FL;
        values[12 + valuesStart] = (w0 >>> 60 | w1 << 4) & 0x1FL;
        values[13 + valuesStart] = w1 >>> 1 & 0x1FL;
        values[14 + valuesStart] = w1 >>> 6 & 0x1FL;
        values[15 + valuesStart] = w1 >>> 11 & 0x1FL;
        values[16 + valuesStart] = w1 >>> 16 & 0x1FL;
        values[17 + valuesStart] = w1 >>> 21 & 0x1FL;
        values[18 + valuesStart] = w1 >>> 26 & 0x1FL;
        values[19 + valuesStart] = w1 >>> 31 & 0x1FL;
        values[20 + valuesStart] = w1 >>> 36 & 0x1FL;
        values[21 + valuesStart] = w1 >>> 41 & 0x1FL;
        values[22 + valuesStart] = w1 >>> 46 & 0x1FL;
        values[23 + valuesStart] = w1 >>> 51 & 0x1FL;
        values[24 + valuesStart] = w1 >>> 56 & 0x1FL;
        values[25 + valuesStart] = (w1 >>> 61 | w2 << 3) & 0x1FL;
        values[26 + valuesStart] = w2 >>> 2 & 0x1FL;
        values[27 + valuesStart] = w2 >>> 7 & 0x1FL;
        values[28 + valuesStart] = w2 >>> 12 & 0x1FL;
        values[29 + valuesStart] = w2 >>> 17 & 0x1FL;
        values[30 + valuesStart] = w2 >>> 22 & 0x1FL;
        values[31 + valuesStart] = w2 >>> 27 & 0x1FL;
        values[32 + valuesStart] = w2 >>> 32 & 0x1FL;
        values[33 + valuesStart] = w2 >>> 37 & 0x1FL;
        values[34 + valuesStart] = w2 >>> 42 & 0x1FL;
        values[35 + valuesStart] = w2 >>> 47 & 0x1FL;
        values[36 + valuesStart] = w2 >>> 52 & 0x1FL;
        values[37 + valuesStart] = w2 >>> 57 & 0x1FL;
        values[38 + valuesStart] = (w2 >>> 62 | w3 << 2) & 0x1FL;
        values[39 + valuesStart] = w3 >>> 3 & 0x1FL;
        values[40 + valuesStart] = w3 >>> 8 & 0x1FL;
        values[41 + valuesStart] = w3 >>> 13 & 0x1FL;
        values[42 + valuesStart] = w3 >>> 18 & 0x1FL;
        values[43 + valuesStart] = w3 >>> 23 & 0x1FL;
        values[44 + valuesStart] = w3 >>> 28 & 0x1FL;
        values[45 + valuesStart] = w3 >>> 33 & 0x1FL;
        values[46 + valuesStart] = w3 >>> 38 & 0x1FL;
        values[47 + valuesStart] = w3 >>> 43 & 0x1FL;
        values[48 + valuesStart] = w3 >>> 48 & 0x1FL;
        values[49 + valuesStart] = w3 >>> 53 & 0x1FL;
        values[50 + valuesStart] = w3 >>> 58 & 0x1FL;
        values[51 + valuesStart] = (w3 >>> 63 | w4 << 1) & 0x1FL;
        values[52 + valuesStart] = w4 >>> 4 & 0x1FL;
        values[53 + valuesStart] = w4 >>> 9 & 0x1FL;
        values[54 + valuesStart] = w4 >>> 14 & 0x1FL;
        values[55 + valuesStart] = w4 >>> 19 & 0x1FL;
        values[56 + valuesStart] = w4 >>> 24 & 0x1FL;
        values[57 + valuesStart] = w4 >>> 29 & 0x1FL;
        values[58 + valuesStart] = w4 >>> 34 & 0x1FL;
        values[59 + valuesStart] = w4 >>> 39 & 0x1FL;
        values[60 + valuesStart] = w4 >>> 44 & 0x1FL;
        values[61 + valuesStart] = w4 >>> 49 & 0x1FL;
        values[62 + valuesStart] = w4 >>> 54 & 0x1FL;
        values[63 + valuesStart] = w4 >>> 59;
        return 40 + packedPtr;
    }

    /**
     * Unpacks 64 6-bit values using 48 bytes, touching 6 words.
     */
    private static long unpack6(long[] values, int valuesStart, long packedPtr) {
        // Access 6 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        values[valuesStart] = w0 & 0x3FL;
        values[1 + valuesStart] = w0 >>> 6 & 0x3FL;
        values[2 + valuesStart] = w0 >>> 12 & 0x3FL;
        values[3 + valuesStart] = w0 >>> 18 & 0x3FL;
        values[4 + valuesStart] = w0 >>> 24 & 0x3FL;
        values[5 + valuesStart] = w0 >>> 30 & 0x3FL;
        values[6 + valuesStart] = w0 >>> 36 & 0x3FL;
        values[7 + valuesStart] = w0 >>> 42 & 0x3FL;
        values[8 + valuesStart] = w0 >>> 48 & 0x3FL;
        values[9 + valuesStart] = w0 >>> 54 & 0x3FL;
        values[10 + valuesStart] = (w0 >>> 60 | w1 << 4) & 0x3FL;
        values[11 + valuesStart] = w1 >>> 2 & 0x3FL;
        values[12 + valuesStart] = w1 >>> 8 & 0x3FL;
        values[13 + valuesStart] = w1 >>> 14 & 0x3FL;
        values[14 + valuesStart] = w1 >>> 20 & 0x3FL;
        values[15 + valuesStart] = w1 >>> 26 & 0x3FL;
        values[16 + valuesStart] = w1 >>> 32 & 0x3FL;
        values[17 + valuesStart] = w1 >>> 38 & 0x3FL;
        values[18 + valuesStart] = w1 >>> 44 & 0x3FL;
        values[19 + valuesStart] = w1 >>> 50 & 0x3FL;
        values[20 + valuesStart] = w1 >>> 56 & 0x3FL;
        values[21 + valuesStart] = (w1 >>> 62 | w2 << 2) & 0x3FL;
        values[22 + valuesStart] = w2 >>> 4 & 0x3FL;
        values[23 + valuesStart] = w2 >>> 10 & 0x3FL;
        values[24 + valuesStart] = w2 >>> 16 & 0x3FL;
        values[25 + valuesStart] = w2 >>> 22 & 0x3FL;
        values[26 + valuesStart] = w2 >>> 28 & 0x3FL;
        values[27 + valuesStart] = w2 >>> 34 & 0x3FL;
        values[28 + valuesStart] = w2 >>> 40 & 0x3FL;
        values[29 + valuesStart] = w2 >>> 46 & 0x3FL;
        values[30 + valuesStart] = w2 >>> 52 & 0x3FL;
        values[31 + valuesStart] = w2 >>> 58;
        values[32 + valuesStart] = w3 & 0x3FL;
        values[33 + valuesStart] = w3 >>> 6 & 0x3FL;
        values[34 + valuesStart] = w3 >>> 12 & 0x3FL;
        values[35 + valuesStart] = w3 >>> 18 & 0x3FL;
        values[36 + valuesStart] = w3 >>> 24 & 0x3FL;
        values[37 + valuesStart] = w3 >>> 30 & 0x3FL;
        values[38 + valuesStart] = w3 >>> 36 & 0x3FL;
        values[39 + valuesStart] = w3 >>> 42 & 0x3FL;
        values[40 + valuesStart] = w3 >>> 48 & 0x3FL;
        values[41 + valuesStart] = w3 >>> 54 & 0x3FL;
        values[42 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0x3FL;
        values[43 + valuesStart] = w4 >>> 2 & 0x3FL;
        values[44 + valuesStart] = w4 >>> 8 & 0x3FL;
        values[45 + valuesStart] = w4 >>> 14 & 0x3FL;
        values[46 + valuesStart] = w4 >>> 20 & 0x3FL;
        values[47 + valuesStart] = w4 >>> 26 & 0x3FL;
        values[48 + valuesStart] = w4 >>> 32 & 0x3FL;
        values[49 + valuesStart] = w4 >>> 38 & 0x3FL;
        values[50 + valuesStart] = w4 >>> 44 & 0x3FL;
        values[51 + valuesStart] = w4 >>> 50 & 0x3FL;
        values[52 + valuesStart] = w4 >>> 56 & 0x3FL;
        values[53 + valuesStart] = (w4 >>> 62 | w5 << 2) & 0x3FL;
        values[54 + valuesStart] = w5 >>> 4 & 0x3FL;
        values[55 + valuesStart] = w5 >>> 10 & 0x3FL;
        values[56 + valuesStart] = w5 >>> 16 & 0x3FL;
        values[57 + valuesStart] = w5 >>> 22 & 0x3FL;
        values[58 + valuesStart] = w5 >>> 28 & 0x3FL;
        values[59 + valuesStart] = w5 >>> 34 & 0x3FL;
        values[60 + valuesStart] = w5 >>> 40 & 0x3FL;
        values[61 + valuesStart] = w5 >>> 46 & 0x3FL;
        values[62 + valuesStart] = w5 >>> 52 & 0x3FL;
        values[63 + valuesStart] = w5 >>> 58;
        return 48 + packedPtr;
    }

    /**
     * Unpacks 64 7-bit values using 56 bytes, touching 7 words.
     */
    private static long unpack7(long[] values, int valuesStart, long packedPtr) {
        // Access 7 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        values[valuesStart] = w0 & 0x7FL;
        values[1 + valuesStart] = w0 >>> 7 & 0x7FL;
        values[2 + valuesStart] = w0 >>> 14 & 0x7FL;
        values[3 + valuesStart] = w0 >>> 21 & 0x7FL;
        values[4 + valuesStart] = w0 >>> 28 & 0x7FL;
        values[5 + valuesStart] = w0 >>> 35 & 0x7FL;
        values[6 + valuesStart] = w0 >>> 42 & 0x7FL;
        values[7 + valuesStart] = w0 >>> 49 & 0x7FL;
        values[8 + valuesStart] = w0 >>> 56 & 0x7FL;
        values[9 + valuesStart] = (w0 >>> 63 | w1 << 1) & 0x7FL;
        values[10 + valuesStart] = w1 >>> 6 & 0x7FL;
        values[11 + valuesStart] = w1 >>> 13 & 0x7FL;
        values[12 + valuesStart] = w1 >>> 20 & 0x7FL;
        values[13 + valuesStart] = w1 >>> 27 & 0x7FL;
        values[14 + valuesStart] = w1 >>> 34 & 0x7FL;
        values[15 + valuesStart] = w1 >>> 41 & 0x7FL;
        values[16 + valuesStart] = w1 >>> 48 & 0x7FL;
        values[17 + valuesStart] = w1 >>> 55 & 0x7FL;
        values[18 + valuesStart] = (w1 >>> 62 | w2 << 2) & 0x7FL;
        values[19 + valuesStart] = w2 >>> 5 & 0x7FL;
        values[20 + valuesStart] = w2 >>> 12 & 0x7FL;
        values[21 + valuesStart] = w2 >>> 19 & 0x7FL;
        values[22 + valuesStart] = w2 >>> 26 & 0x7FL;
        values[23 + valuesStart] = w2 >>> 33 & 0x7FL;
        values[24 + valuesStart] = w2 >>> 40 & 0x7FL;
        values[25 + valuesStart] = w2 >>> 47 & 0x7FL;
        values[26 + valuesStart] = w2 >>> 54 & 0x7FL;
        values[27 + valuesStart] = (w2 >>> 61 | w3 << 3) & 0x7FL;
        values[28 + valuesStart] = w3 >>> 4 & 0x7FL;
        values[29 + valuesStart] = w3 >>> 11 & 0x7FL;
        values[30 + valuesStart] = w3 >>> 18 & 0x7FL;
        values[31 + valuesStart] = w3 >>> 25 & 0x7FL;
        values[32 + valuesStart] = w3 >>> 32 & 0x7FL;
        values[33 + valuesStart] = w3 >>> 39 & 0x7FL;
        values[34 + valuesStart] = w3 >>> 46 & 0x7FL;
        values[35 + valuesStart] = w3 >>> 53 & 0x7FL;
        values[36 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0x7FL;
        values[37 + valuesStart] = w4 >>> 3 & 0x7FL;
        values[38 + valuesStart] = w4 >>> 10 & 0x7FL;
        values[39 + valuesStart] = w4 >>> 17 & 0x7FL;
        values[40 + valuesStart] = w4 >>> 24 & 0x7FL;
        values[41 + valuesStart] = w4 >>> 31 & 0x7FL;
        values[42 + valuesStart] = w4 >>> 38 & 0x7FL;
        values[43 + valuesStart] = w4 >>> 45 & 0x7FL;
        values[44 + valuesStart] = w4 >>> 52 & 0x7FL;
        values[45 + valuesStart] = (w4 >>> 59 | w5 << 5) & 0x7FL;
        values[46 + valuesStart] = w5 >>> 2 & 0x7FL;
        values[47 + valuesStart] = w5 >>> 9 & 0x7FL;
        values[48 + valuesStart] = w5 >>> 16 & 0x7FL;
        values[49 + valuesStart] = w5 >>> 23 & 0x7FL;
        values[50 + valuesStart] = w5 >>> 30 & 0x7FL;
        values[51 + valuesStart] = w5 >>> 37 & 0x7FL;
        values[52 + valuesStart] = w5 >>> 44 & 0x7FL;
        values[53 + valuesStart] = w5 >>> 51 & 0x7FL;
        values[54 + valuesStart] = (w5 >>> 58 | w6 << 6) & 0x7FL;
        values[55 + valuesStart] = w6 >>> 1 & 0x7FL;
        values[56 + valuesStart] = w6 >>> 8 & 0x7FL;
        values[57 + valuesStart] = w6 >>> 15 & 0x7FL;
        values[58 + valuesStart] = w6 >>> 22 & 0x7FL;
        values[59 + valuesStart] = w6 >>> 29 & 0x7FL;
        values[60 + valuesStart] = w6 >>> 36 & 0x7FL;
        values[61 + valuesStart] = w6 >>> 43 & 0x7FL;
        values[62 + valuesStart] = w6 >>> 50 & 0x7FL;
        values[63 + valuesStart] = w6 >>> 57;
        return 56 + packedPtr;
    }

    /**
     * Unpacks 64 8-bit values using 64 bytes, touching 8 words.
     */
    private static long unpack8(long[] values, int valuesStart, long packedPtr) {
        // Access 8 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        values[valuesStart] = w0 & 0xFFL;
        values[1 + valuesStart] = w0 >>> 8 & 0xFFL;
        values[2 + valuesStart] = w0 >>> 16 & 0xFFL;
        values[3 + valuesStart] = w0 >>> 24 & 0xFFL;
        values[4 + valuesStart] = w0 >>> 32 & 0xFFL;
        values[5 + valuesStart] = w0 >>> 40 & 0xFFL;
        values[6 + valuesStart] = w0 >>> 48 & 0xFFL;
        values[7 + valuesStart] = w0 >>> 56;
        values[8 + valuesStart] = w1 & 0xFFL;
        values[9 + valuesStart] = w1 >>> 8 & 0xFFL;
        values[10 + valuesStart] = w1 >>> 16 & 0xFFL;
        values[11 + valuesStart] = w1 >>> 24 & 0xFFL;
        values[12 + valuesStart] = w1 >>> 32 & 0xFFL;
        values[13 + valuesStart] = w1 >>> 40 & 0xFFL;
        values[14 + valuesStart] = w1 >>> 48 & 0xFFL;
        values[15 + valuesStart] = w1 >>> 56;
        values[16 + valuesStart] = w2 & 0xFFL;
        values[17 + valuesStart] = w2 >>> 8 & 0xFFL;
        values[18 + valuesStart] = w2 >>> 16 & 0xFFL;
        values[19 + valuesStart] = w2 >>> 24 & 0xFFL;
        values[20 + valuesStart] = w2 >>> 32 & 0xFFL;
        values[21 + valuesStart] = w2 >>> 40 & 0xFFL;
        values[22 + valuesStart] = w2 >>> 48 & 0xFFL;
        values[23 + valuesStart] = w2 >>> 56;
        values[24 + valuesStart] = w3 & 0xFFL;
        values[25 + valuesStart] = w3 >>> 8 & 0xFFL;
        values[26 + valuesStart] = w3 >>> 16 & 0xFFL;
        values[27 + valuesStart] = w3 >>> 24 & 0xFFL;
        values[28 + valuesStart] = w3 >>> 32 & 0xFFL;
        values[29 + valuesStart] = w3 >>> 40 & 0xFFL;
        values[30 + valuesStart] = w3 >>> 48 & 0xFFL;
        values[31 + valuesStart] = w3 >>> 56;
        values[32 + valuesStart] = w4 & 0xFFL;
        values[33 + valuesStart] = w4 >>> 8 & 0xFFL;
        values[34 + valuesStart] = w4 >>> 16 & 0xFFL;
        values[35 + valuesStart] = w4 >>> 24 & 0xFFL;
        values[36 + valuesStart] = w4 >>> 32 & 0xFFL;
        values[37 + valuesStart] = w4 >>> 40 & 0xFFL;
        values[38 + valuesStart] = w4 >>> 48 & 0xFFL;
        values[39 + valuesStart] = w4 >>> 56;
        values[40 + valuesStart] = w5 & 0xFFL;
        values[41 + valuesStart] = w5 >>> 8 & 0xFFL;
        values[42 + valuesStart] = w5 >>> 16 & 0xFFL;
        values[43 + valuesStart] = w5 >>> 24 & 0xFFL;
        values[44 + valuesStart] = w5 >>> 32 & 0xFFL;
        values[45 + valuesStart] = w5 >>> 40 & 0xFFL;
        values[46 + valuesStart] = w5 >>> 48 & 0xFFL;
        values[47 + valuesStart] = w5 >>> 56;
        values[48 + valuesStart] = w6 & 0xFFL;
        values[49 + valuesStart] = w6 >>> 8 & 0xFFL;
        values[50 + valuesStart] = w6 >>> 16 & 0xFFL;
        values[51 + valuesStart] = w6 >>> 24 & 0xFFL;
        values[52 + valuesStart] = w6 >>> 32 & 0xFFL;
        values[53 + valuesStart] = w6 >>> 40 & 0xFFL;
        values[54 + valuesStart] = w6 >>> 48 & 0xFFL;
        values[55 + valuesStart] = w6 >>> 56;
        values[56 + valuesStart] = w7 & 0xFFL;
        values[57 + valuesStart] = w7 >>> 8 & 0xFFL;
        values[58 + valuesStart] = w7 >>> 16 & 0xFFL;
        values[59 + valuesStart] = w7 >>> 24 & 0xFFL;
        values[60 + valuesStart] = w7 >>> 32 & 0xFFL;
        values[61 + valuesStart] = w7 >>> 40 & 0xFFL;
        values[62 + valuesStart] = w7 >>> 48 & 0xFFL;
        values[63 + valuesStart] = w7 >>> 56;
        return 64 + packedPtr;
    }

    /**
     * Unpacks 64 9-bit values using 72 bytes, touching 9 words.
     */
    private static long unpack9(long[] values, int valuesStart, long packedPtr) {
        // Access 9 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        values[valuesStart] = w0 & 0x1FFL;
        values[1 + valuesStart] = w0 >>> 9 & 0x1FFL;
        values[2 + valuesStart] = w0 >>> 18 & 0x1FFL;
        values[3 + valuesStart] = w0 >>> 27 & 0x1FFL;
        values[4 + valuesStart] = w0 >>> 36 & 0x1FFL;
        values[5 + valuesStart] = w0 >>> 45 & 0x1FFL;
        values[6 + valuesStart] = w0 >>> 54 & 0x1FFL;
        values[7 + valuesStart] = (w0 >>> 63 | w1 << 1) & 0x1FFL;
        values[8 + valuesStart] = w1 >>> 8 & 0x1FFL;
        values[9 + valuesStart] = w1 >>> 17 & 0x1FFL;
        values[10 + valuesStart] = w1 >>> 26 & 0x1FFL;
        values[11 + valuesStart] = w1 >>> 35 & 0x1FFL;
        values[12 + valuesStart] = w1 >>> 44 & 0x1FFL;
        values[13 + valuesStart] = w1 >>> 53 & 0x1FFL;
        values[14 + valuesStart] = (w1 >>> 62 | w2 << 2) & 0x1FFL;
        values[15 + valuesStart] = w2 >>> 7 & 0x1FFL;
        values[16 + valuesStart] = w2 >>> 16 & 0x1FFL;
        values[17 + valuesStart] = w2 >>> 25 & 0x1FFL;
        values[18 + valuesStart] = w2 >>> 34 & 0x1FFL;
        values[19 + valuesStart] = w2 >>> 43 & 0x1FFL;
        values[20 + valuesStart] = w2 >>> 52 & 0x1FFL;
        values[21 + valuesStart] = (w2 >>> 61 | w3 << 3) & 0x1FFL;
        values[22 + valuesStart] = w3 >>> 6 & 0x1FFL;
        values[23 + valuesStart] = w3 >>> 15 & 0x1FFL;
        values[24 + valuesStart] = w3 >>> 24 & 0x1FFL;
        values[25 + valuesStart] = w3 >>> 33 & 0x1FFL;
        values[26 + valuesStart] = w3 >>> 42 & 0x1FFL;
        values[27 + valuesStart] = w3 >>> 51 & 0x1FFL;
        values[28 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0x1FFL;
        values[29 + valuesStart] = w4 >>> 5 & 0x1FFL;
        values[30 + valuesStart] = w4 >>> 14 & 0x1FFL;
        values[31 + valuesStart] = w4 >>> 23 & 0x1FFL;
        values[32 + valuesStart] = w4 >>> 32 & 0x1FFL;
        values[33 + valuesStart] = w4 >>> 41 & 0x1FFL;
        values[34 + valuesStart] = w4 >>> 50 & 0x1FFL;
        values[35 + valuesStart] = (w4 >>> 59 | w5 << 5) & 0x1FFL;
        values[36 + valuesStart] = w5 >>> 4 & 0x1FFL;
        values[37 + valuesStart] = w5 >>> 13 & 0x1FFL;
        values[38 + valuesStart] = w5 >>> 22 & 0x1FFL;
        values[39 + valuesStart] = w5 >>> 31 & 0x1FFL;
        values[40 + valuesStart] = w5 >>> 40 & 0x1FFL;
        values[41 + valuesStart] = w5 >>> 49 & 0x1FFL;
        values[42 + valuesStart] = (w5 >>> 58 | w6 << 6) & 0x1FFL;
        values[43 + valuesStart] = w6 >>> 3 & 0x1FFL;
        values[44 + valuesStart] = w6 >>> 12 & 0x1FFL;
        values[45 + valuesStart] = w6 >>> 21 & 0x1FFL;
        values[46 + valuesStart] = w6 >>> 30 & 0x1FFL;
        values[47 + valuesStart] = w6 >>> 39 & 0x1FFL;
        values[48 + valuesStart] = w6 >>> 48 & 0x1FFL;
        values[49 + valuesStart] = (w6 >>> 57 | w7 << 7) & 0x1FFL;
        values[50 + valuesStart] = w7 >>> 2 & 0x1FFL;
        values[51 + valuesStart] = w7 >>> 11 & 0x1FFL;
        values[52 + valuesStart] = w7 >>> 20 & 0x1FFL;
        values[53 + valuesStart] = w7 >>> 29 & 0x1FFL;
        values[54 + valuesStart] = w7 >>> 38 & 0x1FFL;
        values[55 + valuesStart] = w7 >>> 47 & 0x1FFL;
        values[56 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0x1FFL;
        values[57 + valuesStart] = w8 >>> 1 & 0x1FFL;
        values[58 + valuesStart] = w8 >>> 10 & 0x1FFL;
        values[59 + valuesStart] = w8 >>> 19 & 0x1FFL;
        values[60 + valuesStart] = w8 >>> 28 & 0x1FFL;
        values[61 + valuesStart] = w8 >>> 37 & 0x1FFL;
        values[62 + valuesStart] = w8 >>> 46 & 0x1FFL;
        values[63 + valuesStart] = w8 >>> 55;
        return 72 + packedPtr;
    }

    /**
     * Unpacks 64 10-bit values using 80 bytes, touching 10 words.
     */
    private static long unpack10(long[] values, int valuesStart, long packedPtr) {
        // Access 10 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        values[valuesStart] = w0 & 0x3FFL;
        values[1 + valuesStart] = w0 >>> 10 & 0x3FFL;
        values[2 + valuesStart] = w0 >>> 20 & 0x3FFL;
        values[3 + valuesStart] = w0 >>> 30 & 0x3FFL;
        values[4 + valuesStart] = w0 >>> 40 & 0x3FFL;
        values[5 + valuesStart] = w0 >>> 50 & 0x3FFL;
        values[6 + valuesStart] = (w0 >>> 60 | w1 << 4) & 0x3FFL;
        values[7 + valuesStart] = w1 >>> 6 & 0x3FFL;
        values[8 + valuesStart] = w1 >>> 16 & 0x3FFL;
        values[9 + valuesStart] = w1 >>> 26 & 0x3FFL;
        values[10 + valuesStart] = w1 >>> 36 & 0x3FFL;
        values[11 + valuesStart] = w1 >>> 46 & 0x3FFL;
        values[12 + valuesStart] = (w1 >>> 56 | w2 << 8) & 0x3FFL;
        values[13 + valuesStart] = w2 >>> 2 & 0x3FFL;
        values[14 + valuesStart] = w2 >>> 12 & 0x3FFL;
        values[15 + valuesStart] = w2 >>> 22 & 0x3FFL;
        values[16 + valuesStart] = w2 >>> 32 & 0x3FFL;
        values[17 + valuesStart] = w2 >>> 42 & 0x3FFL;
        values[18 + valuesStart] = w2 >>> 52 & 0x3FFL;
        values[19 + valuesStart] = (w2 >>> 62 | w3 << 2) & 0x3FFL;
        values[20 + valuesStart] = w3 >>> 8 & 0x3FFL;
        values[21 + valuesStart] = w3 >>> 18 & 0x3FFL;
        values[22 + valuesStart] = w3 >>> 28 & 0x3FFL;
        values[23 + valuesStart] = w3 >>> 38 & 0x3FFL;
        values[24 + valuesStart] = w3 >>> 48 & 0x3FFL;
        values[25 + valuesStart] = (w3 >>> 58 | w4 << 6) & 0x3FFL;
        values[26 + valuesStart] = w4 >>> 4 & 0x3FFL;
        values[27 + valuesStart] = w4 >>> 14 & 0x3FFL;
        values[28 + valuesStart] = w4 >>> 24 & 0x3FFL;
        values[29 + valuesStart] = w4 >>> 34 & 0x3FFL;
        values[30 + valuesStart] = w4 >>> 44 & 0x3FFL;
        values[31 + valuesStart] = w4 >>> 54;
        values[32 + valuesStart] = w5 & 0x3FFL;
        values[33 + valuesStart] = w5 >>> 10 & 0x3FFL;
        values[34 + valuesStart] = w5 >>> 20 & 0x3FFL;
        values[35 + valuesStart] = w5 >>> 30 & 0x3FFL;
        values[36 + valuesStart] = w5 >>> 40 & 0x3FFL;
        values[37 + valuesStart] = w5 >>> 50 & 0x3FFL;
        values[38 + valuesStart] = (w5 >>> 60 | w6 << 4) & 0x3FFL;
        values[39 + valuesStart] = w6 >>> 6 & 0x3FFL;
        values[40 + valuesStart] = w6 >>> 16 & 0x3FFL;
        values[41 + valuesStart] = w6 >>> 26 & 0x3FFL;
        values[42 + valuesStart] = w6 >>> 36 & 0x3FFL;
        values[43 + valuesStart] = w6 >>> 46 & 0x3FFL;
        values[44 + valuesStart] = (w6 >>> 56 | w7 << 8) & 0x3FFL;
        values[45 + valuesStart] = w7 >>> 2 & 0x3FFL;
        values[46 + valuesStart] = w7 >>> 12 & 0x3FFL;
        values[47 + valuesStart] = w7 >>> 22 & 0x3FFL;
        values[48 + valuesStart] = w7 >>> 32 & 0x3FFL;
        values[49 + valuesStart] = w7 >>> 42 & 0x3FFL;
        values[50 + valuesStart] = w7 >>> 52 & 0x3FFL;
        values[51 + valuesStart] = (w7 >>> 62 | w8 << 2) & 0x3FFL;
        values[52 + valuesStart] = w8 >>> 8 & 0x3FFL;
        values[53 + valuesStart] = w8 >>> 18 & 0x3FFL;
        values[54 + valuesStart] = w8 >>> 28 & 0x3FFL;
        values[55 + valuesStart] = w8 >>> 38 & 0x3FFL;
        values[56 + valuesStart] = w8 >>> 48 & 0x3FFL;
        values[57 + valuesStart] = (w8 >>> 58 | w9 << 6) & 0x3FFL;
        values[58 + valuesStart] = w9 >>> 4 & 0x3FFL;
        values[59 + valuesStart] = w9 >>> 14 & 0x3FFL;
        values[60 + valuesStart] = w9 >>> 24 & 0x3FFL;
        values[61 + valuesStart] = w9 >>> 34 & 0x3FFL;
        values[62 + valuesStart] = w9 >>> 44 & 0x3FFL;
        values[63 + valuesStart] = w9 >>> 54;
        return 80 + packedPtr;
    }

    /**
     * Unpacks 64 11-bit values using 88 bytes, touching 11 words.
     */
    private static long unpack11(long[] values, int valuesStart, long packedPtr) {
        // Access 11 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        values[valuesStart] = w0 & 0x7FFL;
        values[1 + valuesStart] = w0 >>> 11 & 0x7FFL;
        values[2 + valuesStart] = w0 >>> 22 & 0x7FFL;
        values[3 + valuesStart] = w0 >>> 33 & 0x7FFL;
        values[4 + valuesStart] = w0 >>> 44 & 0x7FFL;
        values[5 + valuesStart] = (w0 >>> 55 | w1 << 9) & 0x7FFL;
        values[6 + valuesStart] = w1 >>> 2 & 0x7FFL;
        values[7 + valuesStart] = w1 >>> 13 & 0x7FFL;
        values[8 + valuesStart] = w1 >>> 24 & 0x7FFL;
        values[9 + valuesStart] = w1 >>> 35 & 0x7FFL;
        values[10 + valuesStart] = w1 >>> 46 & 0x7FFL;
        values[11 + valuesStart] = (w1 >>> 57 | w2 << 7) & 0x7FFL;
        values[12 + valuesStart] = w2 >>> 4 & 0x7FFL;
        values[13 + valuesStart] = w2 >>> 15 & 0x7FFL;
        values[14 + valuesStart] = w2 >>> 26 & 0x7FFL;
        values[15 + valuesStart] = w2 >>> 37 & 0x7FFL;
        values[16 + valuesStart] = w2 >>> 48 & 0x7FFL;
        values[17 + valuesStart] = (w2 >>> 59 | w3 << 5) & 0x7FFL;
        values[18 + valuesStart] = w3 >>> 6 & 0x7FFL;
        values[19 + valuesStart] = w3 >>> 17 & 0x7FFL;
        values[20 + valuesStart] = w3 >>> 28 & 0x7FFL;
        values[21 + valuesStart] = w3 >>> 39 & 0x7FFL;
        values[22 + valuesStart] = w3 >>> 50 & 0x7FFL;
        values[23 + valuesStart] = (w3 >>> 61 | w4 << 3) & 0x7FFL;
        values[24 + valuesStart] = w4 >>> 8 & 0x7FFL;
        values[25 + valuesStart] = w4 >>> 19 & 0x7FFL;
        values[26 + valuesStart] = w4 >>> 30 & 0x7FFL;
        values[27 + valuesStart] = w4 >>> 41 & 0x7FFL;
        values[28 + valuesStart] = w4 >>> 52 & 0x7FFL;
        values[29 + valuesStart] = (w4 >>> 63 | w5 << 1) & 0x7FFL;
        values[30 + valuesStart] = w5 >>> 10 & 0x7FFL;
        values[31 + valuesStart] = w5 >>> 21 & 0x7FFL;
        values[32 + valuesStart] = w5 >>> 32 & 0x7FFL;
        values[33 + valuesStart] = w5 >>> 43 & 0x7FFL;
        values[34 + valuesStart] = (w5 >>> 54 | w6 << 10) & 0x7FFL;
        values[35 + valuesStart] = w6 >>> 1 & 0x7FFL;
        values[36 + valuesStart] = w6 >>> 12 & 0x7FFL;
        values[37 + valuesStart] = w6 >>> 23 & 0x7FFL;
        values[38 + valuesStart] = w6 >>> 34 & 0x7FFL;
        values[39 + valuesStart] = w6 >>> 45 & 0x7FFL;
        values[40 + valuesStart] = (w6 >>> 56 | w7 << 8) & 0x7FFL;
        values[41 + valuesStart] = w7 >>> 3 & 0x7FFL;
        values[42 + valuesStart] = w7 >>> 14 & 0x7FFL;
        values[43 + valuesStart] = w7 >>> 25 & 0x7FFL;
        values[44 + valuesStart] = w7 >>> 36 & 0x7FFL;
        values[45 + valuesStart] = w7 >>> 47 & 0x7FFL;
        values[46 + valuesStart] = (w7 >>> 58 | w8 << 6) & 0x7FFL;
        values[47 + valuesStart] = w8 >>> 5 & 0x7FFL;
        values[48 + valuesStart] = w8 >>> 16 & 0x7FFL;
        values[49 + valuesStart] = w8 >>> 27 & 0x7FFL;
        values[50 + valuesStart] = w8 >>> 38 & 0x7FFL;
        values[51 + valuesStart] = w8 >>> 49 & 0x7FFL;
        values[52 + valuesStart] = (w8 >>> 60 | w9 << 4) & 0x7FFL;
        values[53 + valuesStart] = w9 >>> 7 & 0x7FFL;
        values[54 + valuesStart] = w9 >>> 18 & 0x7FFL;
        values[55 + valuesStart] = w9 >>> 29 & 0x7FFL;
        values[56 + valuesStart] = w9 >>> 40 & 0x7FFL;
        values[57 + valuesStart] = w9 >>> 51 & 0x7FFL;
        values[58 + valuesStart] = (w9 >>> 62 | w10 << 2) & 0x7FFL;
        values[59 + valuesStart] = w10 >>> 9 & 0x7FFL;
        values[60 + valuesStart] = w10 >>> 20 & 0x7FFL;
        values[61 + valuesStart] = w10 >>> 31 & 0x7FFL;
        values[62 + valuesStart] = w10 >>> 42 & 0x7FFL;
        values[63 + valuesStart] = w10 >>> 53;
        return 88 + packedPtr;
    }

    /**
     * Unpacks 64 12-bit values using 96 bytes, touching 12 words.
     */
    private static long unpack12(long[] values, int valuesStart, long packedPtr) {
        // Access 12 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        values[valuesStart] = w0 & 0xFFFL;
        values[1 + valuesStart] = w0 >>> 12 & 0xFFFL;
        values[2 + valuesStart] = w0 >>> 24 & 0xFFFL;
        values[3 + valuesStart] = w0 >>> 36 & 0xFFFL;
        values[4 + valuesStart] = w0 >>> 48 & 0xFFFL;
        values[5 + valuesStart] = (w0 >>> 60 | w1 << 4) & 0xFFFL;
        values[6 + valuesStart] = w1 >>> 8 & 0xFFFL;
        values[7 + valuesStart] = w1 >>> 20 & 0xFFFL;
        values[8 + valuesStart] = w1 >>> 32 & 0xFFFL;
        values[9 + valuesStart] = w1 >>> 44 & 0xFFFL;
        values[10 + valuesStart] = (w1 >>> 56 | w2 << 8) & 0xFFFL;
        values[11 + valuesStart] = w2 >>> 4 & 0xFFFL;
        values[12 + valuesStart] = w2 >>> 16 & 0xFFFL;
        values[13 + valuesStart] = w2 >>> 28 & 0xFFFL;
        values[14 + valuesStart] = w2 >>> 40 & 0xFFFL;
        values[15 + valuesStart] = w2 >>> 52;
        values[16 + valuesStart] = w3 & 0xFFFL;
        values[17 + valuesStart] = w3 >>> 12 & 0xFFFL;
        values[18 + valuesStart] = w3 >>> 24 & 0xFFFL;
        values[19 + valuesStart] = w3 >>> 36 & 0xFFFL;
        values[20 + valuesStart] = w3 >>> 48 & 0xFFFL;
        values[21 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0xFFFL;
        values[22 + valuesStart] = w4 >>> 8 & 0xFFFL;
        values[23 + valuesStart] = w4 >>> 20 & 0xFFFL;
        values[24 + valuesStart] = w4 >>> 32 & 0xFFFL;
        values[25 + valuesStart] = w4 >>> 44 & 0xFFFL;
        values[26 + valuesStart] = (w4 >>> 56 | w5 << 8) & 0xFFFL;
        values[27 + valuesStart] = w5 >>> 4 & 0xFFFL;
        values[28 + valuesStart] = w5 >>> 16 & 0xFFFL;
        values[29 + valuesStart] = w5 >>> 28 & 0xFFFL;
        values[30 + valuesStart] = w5 >>> 40 & 0xFFFL;
        values[31 + valuesStart] = w5 >>> 52;
        values[32 + valuesStart] = w6 & 0xFFFL;
        values[33 + valuesStart] = w6 >>> 12 & 0xFFFL;
        values[34 + valuesStart] = w6 >>> 24 & 0xFFFL;
        values[35 + valuesStart] = w6 >>> 36 & 0xFFFL;
        values[36 + valuesStart] = w6 >>> 48 & 0xFFFL;
        values[37 + valuesStart] = (w6 >>> 60 | w7 << 4) & 0xFFFL;
        values[38 + valuesStart] = w7 >>> 8 & 0xFFFL;
        values[39 + valuesStart] = w7 >>> 20 & 0xFFFL;
        values[40 + valuesStart] = w7 >>> 32 & 0xFFFL;
        values[41 + valuesStart] = w7 >>> 44 & 0xFFFL;
        values[42 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0xFFFL;
        values[43 + valuesStart] = w8 >>> 4 & 0xFFFL;
        values[44 + valuesStart] = w8 >>> 16 & 0xFFFL;
        values[45 + valuesStart] = w8 >>> 28 & 0xFFFL;
        values[46 + valuesStart] = w8 >>> 40 & 0xFFFL;
        values[47 + valuesStart] = w8 >>> 52;
        values[48 + valuesStart] = w9 & 0xFFFL;
        values[49 + valuesStart] = w9 >>> 12 & 0xFFFL;
        values[50 + valuesStart] = w9 >>> 24 & 0xFFFL;
        values[51 + valuesStart] = w9 >>> 36 & 0xFFFL;
        values[52 + valuesStart] = w9 >>> 48 & 0xFFFL;
        values[53 + valuesStart] = (w9 >>> 60 | w10 << 4) & 0xFFFL;
        values[54 + valuesStart] = w10 >>> 8 & 0xFFFL;
        values[55 + valuesStart] = w10 >>> 20 & 0xFFFL;
        values[56 + valuesStart] = w10 >>> 32 & 0xFFFL;
        values[57 + valuesStart] = w10 >>> 44 & 0xFFFL;
        values[58 + valuesStart] = (w10 >>> 56 | w11 << 8) & 0xFFFL;
        values[59 + valuesStart] = w11 >>> 4 & 0xFFFL;
        values[60 + valuesStart] = w11 >>> 16 & 0xFFFL;
        values[61 + valuesStart] = w11 >>> 28 & 0xFFFL;
        values[62 + valuesStart] = w11 >>> 40 & 0xFFFL;
        values[63 + valuesStart] = w11 >>> 52;
        return 96 + packedPtr;
    }

    /**
     * Unpacks 64 13-bit values using 104 bytes, touching 13 words.
     */
    private static long unpack13(long[] values, int valuesStart, long packedPtr) {
        // Access 13 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFL;
        values[1 + valuesStart] = w0 >>> 13 & 0x1FFFL;
        values[2 + valuesStart] = w0 >>> 26 & 0x1FFFL;
        values[3 + valuesStart] = w0 >>> 39 & 0x1FFFL;
        values[4 + valuesStart] = (w0 >>> 52 | w1 << 12) & 0x1FFFL;
        values[5 + valuesStart] = w1 >>> 1 & 0x1FFFL;
        values[6 + valuesStart] = w1 >>> 14 & 0x1FFFL;
        values[7 + valuesStart] = w1 >>> 27 & 0x1FFFL;
        values[8 + valuesStart] = w1 >>> 40 & 0x1FFFL;
        values[9 + valuesStart] = (w1 >>> 53 | w2 << 11) & 0x1FFFL;
        values[10 + valuesStart] = w2 >>> 2 & 0x1FFFL;
        values[11 + valuesStart] = w2 >>> 15 & 0x1FFFL;
        values[12 + valuesStart] = w2 >>> 28 & 0x1FFFL;
        values[13 + valuesStart] = w2 >>> 41 & 0x1FFFL;
        values[14 + valuesStart] = (w2 >>> 54 | w3 << 10) & 0x1FFFL;
        values[15 + valuesStart] = w3 >>> 3 & 0x1FFFL;
        values[16 + valuesStart] = w3 >>> 16 & 0x1FFFL;
        values[17 + valuesStart] = w3 >>> 29 & 0x1FFFL;
        values[18 + valuesStart] = w3 >>> 42 & 0x1FFFL;
        values[19 + valuesStart] = (w3 >>> 55 | w4 << 9) & 0x1FFFL;
        values[20 + valuesStart] = w4 >>> 4 & 0x1FFFL;
        values[21 + valuesStart] = w4 >>> 17 & 0x1FFFL;
        values[22 + valuesStart] = w4 >>> 30 & 0x1FFFL;
        values[23 + valuesStart] = w4 >>> 43 & 0x1FFFL;
        values[24 + valuesStart] = (w4 >>> 56 | w5 << 8) & 0x1FFFL;
        values[25 + valuesStart] = w5 >>> 5 & 0x1FFFL;
        values[26 + valuesStart] = w5 >>> 18 & 0x1FFFL;
        values[27 + valuesStart] = w5 >>> 31 & 0x1FFFL;
        values[28 + valuesStart] = w5 >>> 44 & 0x1FFFL;
        values[29 + valuesStart] = (w5 >>> 57 | w6 << 7) & 0x1FFFL;
        values[30 + valuesStart] = w6 >>> 6 & 0x1FFFL;
        values[31 + valuesStart] = w6 >>> 19 & 0x1FFFL;
        values[32 + valuesStart] = w6 >>> 32 & 0x1FFFL;
        values[33 + valuesStart] = w6 >>> 45 & 0x1FFFL;
        values[34 + valuesStart] = (w6 >>> 58 | w7 << 6) & 0x1FFFL;
        values[35 + valuesStart] = w7 >>> 7 & 0x1FFFL;
        values[36 + valuesStart] = w7 >>> 20 & 0x1FFFL;
        values[37 + valuesStart] = w7 >>> 33 & 0x1FFFL;
        values[38 + valuesStart] = w7 >>> 46 & 0x1FFFL;
        values[39 + valuesStart] = (w7 >>> 59 | w8 << 5) & 0x1FFFL;
        values[40 + valuesStart] = w8 >>> 8 & 0x1FFFL;
        values[41 + valuesStart] = w8 >>> 21 & 0x1FFFL;
        values[42 + valuesStart] = w8 >>> 34 & 0x1FFFL;
        values[43 + valuesStart] = w8 >>> 47 & 0x1FFFL;
        values[44 + valuesStart] = (w8 >>> 60 | w9 << 4) & 0x1FFFL;
        values[45 + valuesStart] = w9 >>> 9 & 0x1FFFL;
        values[46 + valuesStart] = w9 >>> 22 & 0x1FFFL;
        values[47 + valuesStart] = w9 >>> 35 & 0x1FFFL;
        values[48 + valuesStart] = w9 >>> 48 & 0x1FFFL;
        values[49 + valuesStart] = (w9 >>> 61 | w10 << 3) & 0x1FFFL;
        values[50 + valuesStart] = w10 >>> 10 & 0x1FFFL;
        values[51 + valuesStart] = w10 >>> 23 & 0x1FFFL;
        values[52 + valuesStart] = w10 >>> 36 & 0x1FFFL;
        values[53 + valuesStart] = w10 >>> 49 & 0x1FFFL;
        values[54 + valuesStart] = (w10 >>> 62 | w11 << 2) & 0x1FFFL;
        values[55 + valuesStart] = w11 >>> 11 & 0x1FFFL;
        values[56 + valuesStart] = w11 >>> 24 & 0x1FFFL;
        values[57 + valuesStart] = w11 >>> 37 & 0x1FFFL;
        values[58 + valuesStart] = w11 >>> 50 & 0x1FFFL;
        values[59 + valuesStart] = (w11 >>> 63 | w12 << 1) & 0x1FFFL;
        values[60 + valuesStart] = w12 >>> 12 & 0x1FFFL;
        values[61 + valuesStart] = w12 >>> 25 & 0x1FFFL;
        values[62 + valuesStart] = w12 >>> 38 & 0x1FFFL;
        values[63 + valuesStart] = w12 >>> 51;
        return 104 + packedPtr;
    }

    /**
     * Unpacks 64 14-bit values using 112 bytes, touching 14 words.
     */
    private static long unpack14(long[] values, int valuesStart, long packedPtr) {
        // Access 14 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFL;
        values[1 + valuesStart] = w0 >>> 14 & 0x3FFFL;
        values[2 + valuesStart] = w0 >>> 28 & 0x3FFFL;
        values[3 + valuesStart] = w0 >>> 42 & 0x3FFFL;
        values[4 + valuesStart] = (w0 >>> 56 | w1 << 8) & 0x3FFFL;
        values[5 + valuesStart] = w1 >>> 6 & 0x3FFFL;
        values[6 + valuesStart] = w1 >>> 20 & 0x3FFFL;
        values[7 + valuesStart] = w1 >>> 34 & 0x3FFFL;
        values[8 + valuesStart] = w1 >>> 48 & 0x3FFFL;
        values[9 + valuesStart] = (w1 >>> 62 | w2 << 2) & 0x3FFFL;
        values[10 + valuesStart] = w2 >>> 12 & 0x3FFFL;
        values[11 + valuesStart] = w2 >>> 26 & 0x3FFFL;
        values[12 + valuesStart] = w2 >>> 40 & 0x3FFFL;
        values[13 + valuesStart] = (w2 >>> 54 | w3 << 10) & 0x3FFFL;
        values[14 + valuesStart] = w3 >>> 4 & 0x3FFFL;
        values[15 + valuesStart] = w3 >>> 18 & 0x3FFFL;
        values[16 + valuesStart] = w3 >>> 32 & 0x3FFFL;
        values[17 + valuesStart] = w3 >>> 46 & 0x3FFFL;
        values[18 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0x3FFFL;
        values[19 + valuesStart] = w4 >>> 10 & 0x3FFFL;
        values[20 + valuesStart] = w4 >>> 24 & 0x3FFFL;
        values[21 + valuesStart] = w4 >>> 38 & 0x3FFFL;
        values[22 + valuesStart] = (w4 >>> 52 | w5 << 12) & 0x3FFFL;
        values[23 + valuesStart] = w5 >>> 2 & 0x3FFFL;
        values[24 + valuesStart] = w5 >>> 16 & 0x3FFFL;
        values[25 + valuesStart] = w5 >>> 30 & 0x3FFFL;
        values[26 + valuesStart] = w5 >>> 44 & 0x3FFFL;
        values[27 + valuesStart] = (w5 >>> 58 | w6 << 6) & 0x3FFFL;
        values[28 + valuesStart] = w6 >>> 8 & 0x3FFFL;
        values[29 + valuesStart] = w6 >>> 22 & 0x3FFFL;
        values[30 + valuesStart] = w6 >>> 36 & 0x3FFFL;
        values[31 + valuesStart] = w6 >>> 50;
        values[32 + valuesStart] = w7 & 0x3FFFL;
        values[33 + valuesStart] = w7 >>> 14 & 0x3FFFL;
        values[34 + valuesStart] = w7 >>> 28 & 0x3FFFL;
        values[35 + valuesStart] = w7 >>> 42 & 0x3FFFL;
        values[36 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0x3FFFL;
        values[37 + valuesStart] = w8 >>> 6 & 0x3FFFL;
        values[38 + valuesStart] = w8 >>> 20 & 0x3FFFL;
        values[39 + valuesStart] = w8 >>> 34 & 0x3FFFL;
        values[40 + valuesStart] = w8 >>> 48 & 0x3FFFL;
        values[41 + valuesStart] = (w8 >>> 62 | w9 << 2) & 0x3FFFL;
        values[42 + valuesStart] = w9 >>> 12 & 0x3FFFL;
        values[43 + valuesStart] = w9 >>> 26 & 0x3FFFL;
        values[44 + valuesStart] = w9 >>> 40 & 0x3FFFL;
        values[45 + valuesStart] = (w9 >>> 54 | w10 << 10) & 0x3FFFL;
        values[46 + valuesStart] = w10 >>> 4 & 0x3FFFL;
        values[47 + valuesStart] = w10 >>> 18 & 0x3FFFL;
        values[48 + valuesStart] = w10 >>> 32 & 0x3FFFL;
        values[49 + valuesStart] = w10 >>> 46 & 0x3FFFL;
        values[50 + valuesStart] = (w10 >>> 60 | w11 << 4) & 0x3FFFL;
        values[51 + valuesStart] = w11 >>> 10 & 0x3FFFL;
        values[52 + valuesStart] = w11 >>> 24 & 0x3FFFL;
        values[53 + valuesStart] = w11 >>> 38 & 0x3FFFL;
        values[54 + valuesStart] = (w11 >>> 52 | w12 << 12) & 0x3FFFL;
        values[55 + valuesStart] = w12 >>> 2 & 0x3FFFL;
        values[56 + valuesStart] = w12 >>> 16 & 0x3FFFL;
        values[57 + valuesStart] = w12 >>> 30 & 0x3FFFL;
        values[58 + valuesStart] = w12 >>> 44 & 0x3FFFL;
        values[59 + valuesStart] = (w12 >>> 58 | w13 << 6) & 0x3FFFL;
        values[60 + valuesStart] = w13 >>> 8 & 0x3FFFL;
        values[61 + valuesStart] = w13 >>> 22 & 0x3FFFL;
        values[62 + valuesStart] = w13 >>> 36 & 0x3FFFL;
        values[63 + valuesStart] = w13 >>> 50;
        return 112 + packedPtr;
    }

    /**
     * Unpacks 64 15-bit values using 120 bytes, touching 15 words.
     */
    private static long unpack15(long[] values, int valuesStart, long packedPtr) {
        // Access 15 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFL;
        values[1 + valuesStart] = w0 >>> 15 & 0x7FFFL;
        values[2 + valuesStart] = w0 >>> 30 & 0x7FFFL;
        values[3 + valuesStart] = w0 >>> 45 & 0x7FFFL;
        values[4 + valuesStart] = (w0 >>> 60 | w1 << 4) & 0x7FFFL;
        values[5 + valuesStart] = w1 >>> 11 & 0x7FFFL;
        values[6 + valuesStart] = w1 >>> 26 & 0x7FFFL;
        values[7 + valuesStart] = w1 >>> 41 & 0x7FFFL;
        values[8 + valuesStart] = (w1 >>> 56 | w2 << 8) & 0x7FFFL;
        values[9 + valuesStart] = w2 >>> 7 & 0x7FFFL;
        values[10 + valuesStart] = w2 >>> 22 & 0x7FFFL;
        values[11 + valuesStart] = w2 >>> 37 & 0x7FFFL;
        values[12 + valuesStart] = (w2 >>> 52 | w3 << 12) & 0x7FFFL;
        values[13 + valuesStart] = w3 >>> 3 & 0x7FFFL;
        values[14 + valuesStart] = w3 >>> 18 & 0x7FFFL;
        values[15 + valuesStart] = w3 >>> 33 & 0x7FFFL;
        values[16 + valuesStart] = w3 >>> 48 & 0x7FFFL;
        values[17 + valuesStart] = (w3 >>> 63 | w4 << 1) & 0x7FFFL;
        values[18 + valuesStart] = w4 >>> 14 & 0x7FFFL;
        values[19 + valuesStart] = w4 >>> 29 & 0x7FFFL;
        values[20 + valuesStart] = w4 >>> 44 & 0x7FFFL;
        values[21 + valuesStart] = (w4 >>> 59 | w5 << 5) & 0x7FFFL;
        values[22 + valuesStart] = w5 >>> 10 & 0x7FFFL;
        values[23 + valuesStart] = w5 >>> 25 & 0x7FFFL;
        values[24 + valuesStart] = w5 >>> 40 & 0x7FFFL;
        values[25 + valuesStart] = (w5 >>> 55 | w6 << 9) & 0x7FFFL;
        values[26 + valuesStart] = w6 >>> 6 & 0x7FFFL;
        values[27 + valuesStart] = w6 >>> 21 & 0x7FFFL;
        values[28 + valuesStart] = w6 >>> 36 & 0x7FFFL;
        values[29 + valuesStart] = (w6 >>> 51 | w7 << 13) & 0x7FFFL;
        values[30 + valuesStart] = w7 >>> 2 & 0x7FFFL;
        values[31 + valuesStart] = w7 >>> 17 & 0x7FFFL;
        values[32 + valuesStart] = w7 >>> 32 & 0x7FFFL;
        values[33 + valuesStart] = w7 >>> 47 & 0x7FFFL;
        values[34 + valuesStart] = (w7 >>> 62 | w8 << 2) & 0x7FFFL;
        values[35 + valuesStart] = w8 >>> 13 & 0x7FFFL;
        values[36 + valuesStart] = w8 >>> 28 & 0x7FFFL;
        values[37 + valuesStart] = w8 >>> 43 & 0x7FFFL;
        values[38 + valuesStart] = (w8 >>> 58 | w9 << 6) & 0x7FFFL;
        values[39 + valuesStart] = w9 >>> 9 & 0x7FFFL;
        values[40 + valuesStart] = w9 >>> 24 & 0x7FFFL;
        values[41 + valuesStart] = w9 >>> 39 & 0x7FFFL;
        values[42 + valuesStart] = (w9 >>> 54 | w10 << 10) & 0x7FFFL;
        values[43 + valuesStart] = w10 >>> 5 & 0x7FFFL;
        values[44 + valuesStart] = w10 >>> 20 & 0x7FFFL;
        values[45 + valuesStart] = w10 >>> 35 & 0x7FFFL;
        values[46 + valuesStart] = (w10 >>> 50 | w11 << 14) & 0x7FFFL;
        values[47 + valuesStart] = w11 >>> 1 & 0x7FFFL;
        values[48 + valuesStart] = w11 >>> 16 & 0x7FFFL;
        values[49 + valuesStart] = w11 >>> 31 & 0x7FFFL;
        values[50 + valuesStart] = w11 >>> 46 & 0x7FFFL;
        values[51 + valuesStart] = (w11 >>> 61 | w12 << 3) & 0x7FFFL;
        values[52 + valuesStart] = w12 >>> 12 & 0x7FFFL;
        values[53 + valuesStart] = w12 >>> 27 & 0x7FFFL;
        values[54 + valuesStart] = w12 >>> 42 & 0x7FFFL;
        values[55 + valuesStart] = (w12 >>> 57 | w13 << 7) & 0x7FFFL;
        values[56 + valuesStart] = w13 >>> 8 & 0x7FFFL;
        values[57 + valuesStart] = w13 >>> 23 & 0x7FFFL;
        values[58 + valuesStart] = w13 >>> 38 & 0x7FFFL;
        values[59 + valuesStart] = (w13 >>> 53 | w14 << 11) & 0x7FFFL;
        values[60 + valuesStart] = w14 >>> 4 & 0x7FFFL;
        values[61 + valuesStart] = w14 >>> 19 & 0x7FFFL;
        values[62 + valuesStart] = w14 >>> 34 & 0x7FFFL;
        values[63 + valuesStart] = w14 >>> 49;
        return 120 + packedPtr;
    }

    /**
     * Unpacks 64 16-bit values using 128 bytes, touching 16 words.
     */
    private static long unpack16(long[] values, int valuesStart, long packedPtr) {
        // Access 16 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFL;
        values[1 + valuesStart] = w0 >>> 16 & 0xFFFFL;
        values[2 + valuesStart] = w0 >>> 32 & 0xFFFFL;
        values[3 + valuesStart] = w0 >>> 48;
        values[4 + valuesStart] = w1 & 0xFFFFL;
        values[5 + valuesStart] = w1 >>> 16 & 0xFFFFL;
        values[6 + valuesStart] = w1 >>> 32 & 0xFFFFL;
        values[7 + valuesStart] = w1 >>> 48;
        values[8 + valuesStart] = w2 & 0xFFFFL;
        values[9 + valuesStart] = w2 >>> 16 & 0xFFFFL;
        values[10 + valuesStart] = w2 >>> 32 & 0xFFFFL;
        values[11 + valuesStart] = w2 >>> 48;
        values[12 + valuesStart] = w3 & 0xFFFFL;
        values[13 + valuesStart] = w3 >>> 16 & 0xFFFFL;
        values[14 + valuesStart] = w3 >>> 32 & 0xFFFFL;
        values[15 + valuesStart] = w3 >>> 48;
        values[16 + valuesStart] = w4 & 0xFFFFL;
        values[17 + valuesStart] = w4 >>> 16 & 0xFFFFL;
        values[18 + valuesStart] = w4 >>> 32 & 0xFFFFL;
        values[19 + valuesStart] = w4 >>> 48;
        values[20 + valuesStart] = w5 & 0xFFFFL;
        values[21 + valuesStart] = w5 >>> 16 & 0xFFFFL;
        values[22 + valuesStart] = w5 >>> 32 & 0xFFFFL;
        values[23 + valuesStart] = w5 >>> 48;
        values[24 + valuesStart] = w6 & 0xFFFFL;
        values[25 + valuesStart] = w6 >>> 16 & 0xFFFFL;
        values[26 + valuesStart] = w6 >>> 32 & 0xFFFFL;
        values[27 + valuesStart] = w6 >>> 48;
        values[28 + valuesStart] = w7 & 0xFFFFL;
        values[29 + valuesStart] = w7 >>> 16 & 0xFFFFL;
        values[30 + valuesStart] = w7 >>> 32 & 0xFFFFL;
        values[31 + valuesStart] = w7 >>> 48;
        values[32 + valuesStart] = w8 & 0xFFFFL;
        values[33 + valuesStart] = w8 >>> 16 & 0xFFFFL;
        values[34 + valuesStart] = w8 >>> 32 & 0xFFFFL;
        values[35 + valuesStart] = w8 >>> 48;
        values[36 + valuesStart] = w9 & 0xFFFFL;
        values[37 + valuesStart] = w9 >>> 16 & 0xFFFFL;
        values[38 + valuesStart] = w9 >>> 32 & 0xFFFFL;
        values[39 + valuesStart] = w9 >>> 48;
        values[40 + valuesStart] = w10 & 0xFFFFL;
        values[41 + valuesStart] = w10 >>> 16 & 0xFFFFL;
        values[42 + valuesStart] = w10 >>> 32 & 0xFFFFL;
        values[43 + valuesStart] = w10 >>> 48;
        values[44 + valuesStart] = w11 & 0xFFFFL;
        values[45 + valuesStart] = w11 >>> 16 & 0xFFFFL;
        values[46 + valuesStart] = w11 >>> 32 & 0xFFFFL;
        values[47 + valuesStart] = w11 >>> 48;
        values[48 + valuesStart] = w12 & 0xFFFFL;
        values[49 + valuesStart] = w12 >>> 16 & 0xFFFFL;
        values[50 + valuesStart] = w12 >>> 32 & 0xFFFFL;
        values[51 + valuesStart] = w12 >>> 48;
        values[52 + valuesStart] = w13 & 0xFFFFL;
        values[53 + valuesStart] = w13 >>> 16 & 0xFFFFL;
        values[54 + valuesStart] = w13 >>> 32 & 0xFFFFL;
        values[55 + valuesStart] = w13 >>> 48;
        values[56 + valuesStart] = w14 & 0xFFFFL;
        values[57 + valuesStart] = w14 >>> 16 & 0xFFFFL;
        values[58 + valuesStart] = w14 >>> 32 & 0xFFFFL;
        values[59 + valuesStart] = w14 >>> 48;
        values[60 + valuesStart] = w15 & 0xFFFFL;
        values[61 + valuesStart] = w15 >>> 16 & 0xFFFFL;
        values[62 + valuesStart] = w15 >>> 32 & 0xFFFFL;
        values[63 + valuesStart] = w15 >>> 48;
        return 128 + packedPtr;
    }

    /**
     * Unpacks 64 17-bit values using 136 bytes, touching 17 words.
     */
    private static long unpack17(long[] values, int valuesStart, long packedPtr) {
        // Access 17 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFL;
        values[1 + valuesStart] = w0 >>> 17 & 0x1FFFFL;
        values[2 + valuesStart] = w0 >>> 34 & 0x1FFFFL;
        values[3 + valuesStart] = (w0 >>> 51 | w1 << 13) & 0x1FFFFL;
        values[4 + valuesStart] = w1 >>> 4 & 0x1FFFFL;
        values[5 + valuesStart] = w1 >>> 21 & 0x1FFFFL;
        values[6 + valuesStart] = w1 >>> 38 & 0x1FFFFL;
        values[7 + valuesStart] = (w1 >>> 55 | w2 << 9) & 0x1FFFFL;
        values[8 + valuesStart] = w2 >>> 8 & 0x1FFFFL;
        values[9 + valuesStart] = w2 >>> 25 & 0x1FFFFL;
        values[10 + valuesStart] = w2 >>> 42 & 0x1FFFFL;
        values[11 + valuesStart] = (w2 >>> 59 | w3 << 5) & 0x1FFFFL;
        values[12 + valuesStart] = w3 >>> 12 & 0x1FFFFL;
        values[13 + valuesStart] = w3 >>> 29 & 0x1FFFFL;
        values[14 + valuesStart] = w3 >>> 46 & 0x1FFFFL;
        values[15 + valuesStart] = (w3 >>> 63 | w4 << 1) & 0x1FFFFL;
        values[16 + valuesStart] = w4 >>> 16 & 0x1FFFFL;
        values[17 + valuesStart] = w4 >>> 33 & 0x1FFFFL;
        values[18 + valuesStart] = (w4 >>> 50 | w5 << 14) & 0x1FFFFL;
        values[19 + valuesStart] = w5 >>> 3 & 0x1FFFFL;
        values[20 + valuesStart] = w5 >>> 20 & 0x1FFFFL;
        values[21 + valuesStart] = w5 >>> 37 & 0x1FFFFL;
        values[22 + valuesStart] = (w5 >>> 54 | w6 << 10) & 0x1FFFFL;
        values[23 + valuesStart] = w6 >>> 7 & 0x1FFFFL;
        values[24 + valuesStart] = w6 >>> 24 & 0x1FFFFL;
        values[25 + valuesStart] = w6 >>> 41 & 0x1FFFFL;
        values[26 + valuesStart] = (w6 >>> 58 | w7 << 6) & 0x1FFFFL;
        values[27 + valuesStart] = w7 >>> 11 & 0x1FFFFL;
        values[28 + valuesStart] = w7 >>> 28 & 0x1FFFFL;
        values[29 + valuesStart] = w7 >>> 45 & 0x1FFFFL;
        values[30 + valuesStart] = (w7 >>> 62 | w8 << 2) & 0x1FFFFL;
        values[31 + valuesStart] = w8 >>> 15 & 0x1FFFFL;
        values[32 + valuesStart] = w8 >>> 32 & 0x1FFFFL;
        values[33 + valuesStart] = (w8 >>> 49 | w9 << 15) & 0x1FFFFL;
        values[34 + valuesStart] = w9 >>> 2 & 0x1FFFFL;
        values[35 + valuesStart] = w9 >>> 19 & 0x1FFFFL;
        values[36 + valuesStart] = w9 >>> 36 & 0x1FFFFL;
        values[37 + valuesStart] = (w9 >>> 53 | w10 << 11) & 0x1FFFFL;
        values[38 + valuesStart] = w10 >>> 6 & 0x1FFFFL;
        values[39 + valuesStart] = w10 >>> 23 & 0x1FFFFL;
        values[40 + valuesStart] = w10 >>> 40 & 0x1FFFFL;
        values[41 + valuesStart] = (w10 >>> 57 | w11 << 7) & 0x1FFFFL;
        values[42 + valuesStart] = w11 >>> 10 & 0x1FFFFL;
        values[43 + valuesStart] = w11 >>> 27 & 0x1FFFFL;
        values[44 + valuesStart] = w11 >>> 44 & 0x1FFFFL;
        values[45 + valuesStart] = (w11 >>> 61 | w12 << 3) & 0x1FFFFL;
        values[46 + valuesStart] = w12 >>> 14 & 0x1FFFFL;
        values[47 + valuesStart] = w12 >>> 31 & 0x1FFFFL;
        values[48 + valuesStart] = (w12 >>> 48 | w13 << 16) & 0x1FFFFL;
        values[49 + valuesStart] = w13 >>> 1 & 0x1FFFFL;
        values[50 + valuesStart] = w13 >>> 18 & 0x1FFFFL;
        values[51 + valuesStart] = w13 >>> 35 & 0x1FFFFL;
        values[52 + valuesStart] = (w13 >>> 52 | w14 << 12) & 0x1FFFFL;
        values[53 + valuesStart] = w14 >>> 5 & 0x1FFFFL;
        values[54 + valuesStart] = w14 >>> 22 & 0x1FFFFL;
        values[55 + valuesStart] = w14 >>> 39 & 0x1FFFFL;
        values[56 + valuesStart] = (w14 >>> 56 | w15 << 8) & 0x1FFFFL;
        values[57 + valuesStart] = w15 >>> 9 & 0x1FFFFL;
        values[58 + valuesStart] = w15 >>> 26 & 0x1FFFFL;
        values[59 + valuesStart] = w15 >>> 43 & 0x1FFFFL;
        values[60 + valuesStart] = (w15 >>> 60 | w16 << 4) & 0x1FFFFL;
        values[61 + valuesStart] = w16 >>> 13 & 0x1FFFFL;
        values[62 + valuesStart] = w16 >>> 30 & 0x1FFFFL;
        values[63 + valuesStart] = w16 >>> 47;
        return 136 + packedPtr;
    }

    /**
     * Unpacks 64 18-bit values using 144 bytes, touching 18 words.
     */
    private static long unpack18(long[] values, int valuesStart, long packedPtr) {
        // Access 18 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFL;
        values[1 + valuesStart] = w0 >>> 18 & 0x3FFFFL;
        values[2 + valuesStart] = w0 >>> 36 & 0x3FFFFL;
        values[3 + valuesStart] = (w0 >>> 54 | w1 << 10) & 0x3FFFFL;
        values[4 + valuesStart] = w1 >>> 8 & 0x3FFFFL;
        values[5 + valuesStart] = w1 >>> 26 & 0x3FFFFL;
        values[6 + valuesStart] = w1 >>> 44 & 0x3FFFFL;
        values[7 + valuesStart] = (w1 >>> 62 | w2 << 2) & 0x3FFFFL;
        values[8 + valuesStart] = w2 >>> 16 & 0x3FFFFL;
        values[9 + valuesStart] = w2 >>> 34 & 0x3FFFFL;
        values[10 + valuesStart] = (w2 >>> 52 | w3 << 12) & 0x3FFFFL;
        values[11 + valuesStart] = w3 >>> 6 & 0x3FFFFL;
        values[12 + valuesStart] = w3 >>> 24 & 0x3FFFFL;
        values[13 + valuesStart] = w3 >>> 42 & 0x3FFFFL;
        values[14 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0x3FFFFL;
        values[15 + valuesStart] = w4 >>> 14 & 0x3FFFFL;
        values[16 + valuesStart] = w4 >>> 32 & 0x3FFFFL;
        values[17 + valuesStart] = (w4 >>> 50 | w5 << 14) & 0x3FFFFL;
        values[18 + valuesStart] = w5 >>> 4 & 0x3FFFFL;
        values[19 + valuesStart] = w5 >>> 22 & 0x3FFFFL;
        values[20 + valuesStart] = w5 >>> 40 & 0x3FFFFL;
        values[21 + valuesStart] = (w5 >>> 58 | w6 << 6) & 0x3FFFFL;
        values[22 + valuesStart] = w6 >>> 12 & 0x3FFFFL;
        values[23 + valuesStart] = w6 >>> 30 & 0x3FFFFL;
        values[24 + valuesStart] = (w6 >>> 48 | w7 << 16) & 0x3FFFFL;
        values[25 + valuesStart] = w7 >>> 2 & 0x3FFFFL;
        values[26 + valuesStart] = w7 >>> 20 & 0x3FFFFL;
        values[27 + valuesStart] = w7 >>> 38 & 0x3FFFFL;
        values[28 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0x3FFFFL;
        values[29 + valuesStart] = w8 >>> 10 & 0x3FFFFL;
        values[30 + valuesStart] = w8 >>> 28 & 0x3FFFFL;
        values[31 + valuesStart] = w8 >>> 46;
        values[32 + valuesStart] = w9 & 0x3FFFFL;
        values[33 + valuesStart] = w9 >>> 18 & 0x3FFFFL;
        values[34 + valuesStart] = w9 >>> 36 & 0x3FFFFL;
        values[35 + valuesStart] = (w9 >>> 54 | w10 << 10) & 0x3FFFFL;
        values[36 + valuesStart] = w10 >>> 8 & 0x3FFFFL;
        values[37 + valuesStart] = w10 >>> 26 & 0x3FFFFL;
        values[38 + valuesStart] = w10 >>> 44 & 0x3FFFFL;
        values[39 + valuesStart] = (w10 >>> 62 | w11 << 2) & 0x3FFFFL;
        values[40 + valuesStart] = w11 >>> 16 & 0x3FFFFL;
        values[41 + valuesStart] = w11 >>> 34 & 0x3FFFFL;
        values[42 + valuesStart] = (w11 >>> 52 | w12 << 12) & 0x3FFFFL;
        values[43 + valuesStart] = w12 >>> 6 & 0x3FFFFL;
        values[44 + valuesStart] = w12 >>> 24 & 0x3FFFFL;
        values[45 + valuesStart] = w12 >>> 42 & 0x3FFFFL;
        values[46 + valuesStart] = (w12 >>> 60 | w13 << 4) & 0x3FFFFL;
        values[47 + valuesStart] = w13 >>> 14 & 0x3FFFFL;
        values[48 + valuesStart] = w13 >>> 32 & 0x3FFFFL;
        values[49 + valuesStart] = (w13 >>> 50 | w14 << 14) & 0x3FFFFL;
        values[50 + valuesStart] = w14 >>> 4 & 0x3FFFFL;
        values[51 + valuesStart] = w14 >>> 22 & 0x3FFFFL;
        values[52 + valuesStart] = w14 >>> 40 & 0x3FFFFL;
        values[53 + valuesStart] = (w14 >>> 58 | w15 << 6) & 0x3FFFFL;
        values[54 + valuesStart] = w15 >>> 12 & 0x3FFFFL;
        values[55 + valuesStart] = w15 >>> 30 & 0x3FFFFL;
        values[56 + valuesStart] = (w15 >>> 48 | w16 << 16) & 0x3FFFFL;
        values[57 + valuesStart] = w16 >>> 2 & 0x3FFFFL;
        values[58 + valuesStart] = w16 >>> 20 & 0x3FFFFL;
        values[59 + valuesStart] = w16 >>> 38 & 0x3FFFFL;
        values[60 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0x3FFFFL;
        values[61 + valuesStart] = w17 >>> 10 & 0x3FFFFL;
        values[62 + valuesStart] = w17 >>> 28 & 0x3FFFFL;
        values[63 + valuesStart] = w17 >>> 46;
        return 144 + packedPtr;
    }

    /**
     * Unpacks 64 19-bit values using 152 bytes, touching 19 words.
     */
    private static long unpack19(long[] values, int valuesStart, long packedPtr) {
        // Access 19 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFL;
        values[1 + valuesStart] = w0 >>> 19 & 0x7FFFFL;
        values[2 + valuesStart] = w0 >>> 38 & 0x7FFFFL;
        values[3 + valuesStart] = (w0 >>> 57 | w1 << 7) & 0x7FFFFL;
        values[4 + valuesStart] = w1 >>> 12 & 0x7FFFFL;
        values[5 + valuesStart] = w1 >>> 31 & 0x7FFFFL;
        values[6 + valuesStart] = (w1 >>> 50 | w2 << 14) & 0x7FFFFL;
        values[7 + valuesStart] = w2 >>> 5 & 0x7FFFFL;
        values[8 + valuesStart] = w2 >>> 24 & 0x7FFFFL;
        values[9 + valuesStart] = w2 >>> 43 & 0x7FFFFL;
        values[10 + valuesStart] = (w2 >>> 62 | w3 << 2) & 0x7FFFFL;
        values[11 + valuesStart] = w3 >>> 17 & 0x7FFFFL;
        values[12 + valuesStart] = w3 >>> 36 & 0x7FFFFL;
        values[13 + valuesStart] = (w3 >>> 55 | w4 << 9) & 0x7FFFFL;
        values[14 + valuesStart] = w4 >>> 10 & 0x7FFFFL;
        values[15 + valuesStart] = w4 >>> 29 & 0x7FFFFL;
        values[16 + valuesStart] = (w4 >>> 48 | w5 << 16) & 0x7FFFFL;
        values[17 + valuesStart] = w5 >>> 3 & 0x7FFFFL;
        values[18 + valuesStart] = w5 >>> 22 & 0x7FFFFL;
        values[19 + valuesStart] = w5 >>> 41 & 0x7FFFFL;
        values[20 + valuesStart] = (w5 >>> 60 | w6 << 4) & 0x7FFFFL;
        values[21 + valuesStart] = w6 >>> 15 & 0x7FFFFL;
        values[22 + valuesStart] = w6 >>> 34 & 0x7FFFFL;
        values[23 + valuesStart] = (w6 >>> 53 | w7 << 11) & 0x7FFFFL;
        values[24 + valuesStart] = w7 >>> 8 & 0x7FFFFL;
        values[25 + valuesStart] = w7 >>> 27 & 0x7FFFFL;
        values[26 + valuesStart] = (w7 >>> 46 | w8 << 18) & 0x7FFFFL;
        values[27 + valuesStart] = w8 >>> 1 & 0x7FFFFL;
        values[28 + valuesStart] = w8 >>> 20 & 0x7FFFFL;
        values[29 + valuesStart] = w8 >>> 39 & 0x7FFFFL;
        values[30 + valuesStart] = (w8 >>> 58 | w9 << 6) & 0x7FFFFL;
        values[31 + valuesStart] = w9 >>> 13 & 0x7FFFFL;
        values[32 + valuesStart] = w9 >>> 32 & 0x7FFFFL;
        values[33 + valuesStart] = (w9 >>> 51 | w10 << 13) & 0x7FFFFL;
        values[34 + valuesStart] = w10 >>> 6 & 0x7FFFFL;
        values[35 + valuesStart] = w10 >>> 25 & 0x7FFFFL;
        values[36 + valuesStart] = w10 >>> 44 & 0x7FFFFL;
        values[37 + valuesStart] = (w10 >>> 63 | w11 << 1) & 0x7FFFFL;
        values[38 + valuesStart] = w11 >>> 18 & 0x7FFFFL;
        values[39 + valuesStart] = w11 >>> 37 & 0x7FFFFL;
        values[40 + valuesStart] = (w11 >>> 56 | w12 << 8) & 0x7FFFFL;
        values[41 + valuesStart] = w12 >>> 11 & 0x7FFFFL;
        values[42 + valuesStart] = w12 >>> 30 & 0x7FFFFL;
        values[43 + valuesStart] = (w12 >>> 49 | w13 << 15) & 0x7FFFFL;
        values[44 + valuesStart] = w13 >>> 4 & 0x7FFFFL;
        values[45 + valuesStart] = w13 >>> 23 & 0x7FFFFL;
        values[46 + valuesStart] = w13 >>> 42 & 0x7FFFFL;
        values[47 + valuesStart] = (w13 >>> 61 | w14 << 3) & 0x7FFFFL;
        values[48 + valuesStart] = w14 >>> 16 & 0x7FFFFL;
        values[49 + valuesStart] = w14 >>> 35 & 0x7FFFFL;
        values[50 + valuesStart] = (w14 >>> 54 | w15 << 10) & 0x7FFFFL;
        values[51 + valuesStart] = w15 >>> 9 & 0x7FFFFL;
        values[52 + valuesStart] = w15 >>> 28 & 0x7FFFFL;
        values[53 + valuesStart] = (w15 >>> 47 | w16 << 17) & 0x7FFFFL;
        values[54 + valuesStart] = w16 >>> 2 & 0x7FFFFL;
        values[55 + valuesStart] = w16 >>> 21 & 0x7FFFFL;
        values[56 + valuesStart] = w16 >>> 40 & 0x7FFFFL;
        values[57 + valuesStart] = (w16 >>> 59 | w17 << 5) & 0x7FFFFL;
        values[58 + valuesStart] = w17 >>> 14 & 0x7FFFFL;
        values[59 + valuesStart] = w17 >>> 33 & 0x7FFFFL;
        values[60 + valuesStart] = (w17 >>> 52 | w18 << 12) & 0x7FFFFL;
        values[61 + valuesStart] = w18 >>> 7 & 0x7FFFFL;
        values[62 + valuesStart] = w18 >>> 26 & 0x7FFFFL;
        values[63 + valuesStart] = w18 >>> 45;
        return 152 + packedPtr;
    }

    /**
     * Unpacks 64 20-bit values using 160 bytes, touching 20 words.
     */
    private static long unpack20(long[] values, int valuesStart, long packedPtr) {
        // Access 20 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFL;
        values[1 + valuesStart] = w0 >>> 20 & 0xFFFFFL;
        values[2 + valuesStart] = w0 >>> 40 & 0xFFFFFL;
        values[3 + valuesStart] = (w0 >>> 60 | w1 << 4) & 0xFFFFFL;
        values[4 + valuesStart] = w1 >>> 16 & 0xFFFFFL;
        values[5 + valuesStart] = w1 >>> 36 & 0xFFFFFL;
        values[6 + valuesStart] = (w1 >>> 56 | w2 << 8) & 0xFFFFFL;
        values[7 + valuesStart] = w2 >>> 12 & 0xFFFFFL;
        values[8 + valuesStart] = w2 >>> 32 & 0xFFFFFL;
        values[9 + valuesStart] = (w2 >>> 52 | w3 << 12) & 0xFFFFFL;
        values[10 + valuesStart] = w3 >>> 8 & 0xFFFFFL;
        values[11 + valuesStart] = w3 >>> 28 & 0xFFFFFL;
        values[12 + valuesStart] = (w3 >>> 48 | w4 << 16) & 0xFFFFFL;
        values[13 + valuesStart] = w4 >>> 4 & 0xFFFFFL;
        values[14 + valuesStart] = w4 >>> 24 & 0xFFFFFL;
        values[15 + valuesStart] = w4 >>> 44;
        values[16 + valuesStart] = w5 & 0xFFFFFL;
        values[17 + valuesStart] = w5 >>> 20 & 0xFFFFFL;
        values[18 + valuesStart] = w5 >>> 40 & 0xFFFFFL;
        values[19 + valuesStart] = (w5 >>> 60 | w6 << 4) & 0xFFFFFL;
        values[20 + valuesStart] = w6 >>> 16 & 0xFFFFFL;
        values[21 + valuesStart] = w6 >>> 36 & 0xFFFFFL;
        values[22 + valuesStart] = (w6 >>> 56 | w7 << 8) & 0xFFFFFL;
        values[23 + valuesStart] = w7 >>> 12 & 0xFFFFFL;
        values[24 + valuesStart] = w7 >>> 32 & 0xFFFFFL;
        values[25 + valuesStart] = (w7 >>> 52 | w8 << 12) & 0xFFFFFL;
        values[26 + valuesStart] = w8 >>> 8 & 0xFFFFFL;
        values[27 + valuesStart] = w8 >>> 28 & 0xFFFFFL;
        values[28 + valuesStart] = (w8 >>> 48 | w9 << 16) & 0xFFFFFL;
        values[29 + valuesStart] = w9 >>> 4 & 0xFFFFFL;
        values[30 + valuesStart] = w9 >>> 24 & 0xFFFFFL;
        values[31 + valuesStart] = w9 >>> 44;
        values[32 + valuesStart] = w10 & 0xFFFFFL;
        values[33 + valuesStart] = w10 >>> 20 & 0xFFFFFL;
        values[34 + valuesStart] = w10 >>> 40 & 0xFFFFFL;
        values[35 + valuesStart] = (w10 >>> 60 | w11 << 4) & 0xFFFFFL;
        values[36 + valuesStart] = w11 >>> 16 & 0xFFFFFL;
        values[37 + valuesStart] = w11 >>> 36 & 0xFFFFFL;
        values[38 + valuesStart] = (w11 >>> 56 | w12 << 8) & 0xFFFFFL;
        values[39 + valuesStart] = w12 >>> 12 & 0xFFFFFL;
        values[40 + valuesStart] = w12 >>> 32 & 0xFFFFFL;
        values[41 + valuesStart] = (w12 >>> 52 | w13 << 12) & 0xFFFFFL;
        values[42 + valuesStart] = w13 >>> 8 & 0xFFFFFL;
        values[43 + valuesStart] = w13 >>> 28 & 0xFFFFFL;
        values[44 + valuesStart] = (w13 >>> 48 | w14 << 16) & 0xFFFFFL;
        values[45 + valuesStart] = w14 >>> 4 & 0xFFFFFL;
        values[46 + valuesStart] = w14 >>> 24 & 0xFFFFFL;
        values[47 + valuesStart] = w14 >>> 44;
        values[48 + valuesStart] = w15 & 0xFFFFFL;
        values[49 + valuesStart] = w15 >>> 20 & 0xFFFFFL;
        values[50 + valuesStart] = w15 >>> 40 & 0xFFFFFL;
        values[51 + valuesStart] = (w15 >>> 60 | w16 << 4) & 0xFFFFFL;
        values[52 + valuesStart] = w16 >>> 16 & 0xFFFFFL;
        values[53 + valuesStart] = w16 >>> 36 & 0xFFFFFL;
        values[54 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0xFFFFFL;
        values[55 + valuesStart] = w17 >>> 12 & 0xFFFFFL;
        values[56 + valuesStart] = w17 >>> 32 & 0xFFFFFL;
        values[57 + valuesStart] = (w17 >>> 52 | w18 << 12) & 0xFFFFFL;
        values[58 + valuesStart] = w18 >>> 8 & 0xFFFFFL;
        values[59 + valuesStart] = w18 >>> 28 & 0xFFFFFL;
        values[60 + valuesStart] = (w18 >>> 48 | w19 << 16) & 0xFFFFFL;
        values[61 + valuesStart] = w19 >>> 4 & 0xFFFFFL;
        values[62 + valuesStart] = w19 >>> 24 & 0xFFFFFL;
        values[63 + valuesStart] = w19 >>> 44;
        return 160 + packedPtr;
    }

    /**
     * Unpacks 64 21-bit values using 168 bytes, touching 21 words.
     */
    private static long unpack21(long[] values, int valuesStart, long packedPtr) {
        // Access 21 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFL;
        values[1 + valuesStart] = w0 >>> 21 & 0x1FFFFFL;
        values[2 + valuesStart] = w0 >>> 42 & 0x1FFFFFL;
        values[3 + valuesStart] = (w0 >>> 63 | w1 << 1) & 0x1FFFFFL;
        values[4 + valuesStart] = w1 >>> 20 & 0x1FFFFFL;
        values[5 + valuesStart] = w1 >>> 41 & 0x1FFFFFL;
        values[6 + valuesStart] = (w1 >>> 62 | w2 << 2) & 0x1FFFFFL;
        values[7 + valuesStart] = w2 >>> 19 & 0x1FFFFFL;
        values[8 + valuesStart] = w2 >>> 40 & 0x1FFFFFL;
        values[9 + valuesStart] = (w2 >>> 61 | w3 << 3) & 0x1FFFFFL;
        values[10 + valuesStart] = w3 >>> 18 & 0x1FFFFFL;
        values[11 + valuesStart] = w3 >>> 39 & 0x1FFFFFL;
        values[12 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0x1FFFFFL;
        values[13 + valuesStart] = w4 >>> 17 & 0x1FFFFFL;
        values[14 + valuesStart] = w4 >>> 38 & 0x1FFFFFL;
        values[15 + valuesStart] = (w4 >>> 59 | w5 << 5) & 0x1FFFFFL;
        values[16 + valuesStart] = w5 >>> 16 & 0x1FFFFFL;
        values[17 + valuesStart] = w5 >>> 37 & 0x1FFFFFL;
        values[18 + valuesStart] = (w5 >>> 58 | w6 << 6) & 0x1FFFFFL;
        values[19 + valuesStart] = w6 >>> 15 & 0x1FFFFFL;
        values[20 + valuesStart] = w6 >>> 36 & 0x1FFFFFL;
        values[21 + valuesStart] = (w6 >>> 57 | w7 << 7) & 0x1FFFFFL;
        values[22 + valuesStart] = w7 >>> 14 & 0x1FFFFFL;
        values[23 + valuesStart] = w7 >>> 35 & 0x1FFFFFL;
        values[24 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0x1FFFFFL;
        values[25 + valuesStart] = w8 >>> 13 & 0x1FFFFFL;
        values[26 + valuesStart] = w8 >>> 34 & 0x1FFFFFL;
        values[27 + valuesStart] = (w8 >>> 55 | w9 << 9) & 0x1FFFFFL;
        values[28 + valuesStart] = w9 >>> 12 & 0x1FFFFFL;
        values[29 + valuesStart] = w9 >>> 33 & 0x1FFFFFL;
        values[30 + valuesStart] = (w9 >>> 54 | w10 << 10) & 0x1FFFFFL;
        values[31 + valuesStart] = w10 >>> 11 & 0x1FFFFFL;
        values[32 + valuesStart] = w10 >>> 32 & 0x1FFFFFL;
        values[33 + valuesStart] = (w10 >>> 53 | w11 << 11) & 0x1FFFFFL;
        values[34 + valuesStart] = w11 >>> 10 & 0x1FFFFFL;
        values[35 + valuesStart] = w11 >>> 31 & 0x1FFFFFL;
        values[36 + valuesStart] = (w11 >>> 52 | w12 << 12) & 0x1FFFFFL;
        values[37 + valuesStart] = w12 >>> 9 & 0x1FFFFFL;
        values[38 + valuesStart] = w12 >>> 30 & 0x1FFFFFL;
        values[39 + valuesStart] = (w12 >>> 51 | w13 << 13) & 0x1FFFFFL;
        values[40 + valuesStart] = w13 >>> 8 & 0x1FFFFFL;
        values[41 + valuesStart] = w13 >>> 29 & 0x1FFFFFL;
        values[42 + valuesStart] = (w13 >>> 50 | w14 << 14) & 0x1FFFFFL;
        values[43 + valuesStart] = w14 >>> 7 & 0x1FFFFFL;
        values[44 + valuesStart] = w14 >>> 28 & 0x1FFFFFL;
        values[45 + valuesStart] = (w14 >>> 49 | w15 << 15) & 0x1FFFFFL;
        values[46 + valuesStart] = w15 >>> 6 & 0x1FFFFFL;
        values[47 + valuesStart] = w15 >>> 27 & 0x1FFFFFL;
        values[48 + valuesStart] = (w15 >>> 48 | w16 << 16) & 0x1FFFFFL;
        values[49 + valuesStart] = w16 >>> 5 & 0x1FFFFFL;
        values[50 + valuesStart] = w16 >>> 26 & 0x1FFFFFL;
        values[51 + valuesStart] = (w16 >>> 47 | w17 << 17) & 0x1FFFFFL;
        values[52 + valuesStart] = w17 >>> 4 & 0x1FFFFFL;
        values[53 + valuesStart] = w17 >>> 25 & 0x1FFFFFL;
        values[54 + valuesStart] = (w17 >>> 46 | w18 << 18) & 0x1FFFFFL;
        values[55 + valuesStart] = w18 >>> 3 & 0x1FFFFFL;
        values[56 + valuesStart] = w18 >>> 24 & 0x1FFFFFL;
        values[57 + valuesStart] = (w18 >>> 45 | w19 << 19) & 0x1FFFFFL;
        values[58 + valuesStart] = w19 >>> 2 & 0x1FFFFFL;
        values[59 + valuesStart] = w19 >>> 23 & 0x1FFFFFL;
        values[60 + valuesStart] = (w19 >>> 44 | w20 << 20) & 0x1FFFFFL;
        values[61 + valuesStart] = w20 >>> 1 & 0x1FFFFFL;
        values[62 + valuesStart] = w20 >>> 22 & 0x1FFFFFL;
        values[63 + valuesStart] = w20 >>> 43;
        return 168 + packedPtr;
    }

    /**
     * Unpacks 64 22-bit values using 176 bytes, touching 22 words.
     */
    private static long unpack22(long[] values, int valuesStart, long packedPtr) {
        // Access 22 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFL;
        values[1 + valuesStart] = w0 >>> 22 & 0x3FFFFFL;
        values[2 + valuesStart] = (w0 >>> 44 | w1 << 20) & 0x3FFFFFL;
        values[3 + valuesStart] = w1 >>> 2 & 0x3FFFFFL;
        values[4 + valuesStart] = w1 >>> 24 & 0x3FFFFFL;
        values[5 + valuesStart] = (w1 >>> 46 | w2 << 18) & 0x3FFFFFL;
        values[6 + valuesStart] = w2 >>> 4 & 0x3FFFFFL;
        values[7 + valuesStart] = w2 >>> 26 & 0x3FFFFFL;
        values[8 + valuesStart] = (w2 >>> 48 | w3 << 16) & 0x3FFFFFL;
        values[9 + valuesStart] = w3 >>> 6 & 0x3FFFFFL;
        values[10 + valuesStart] = w3 >>> 28 & 0x3FFFFFL;
        values[11 + valuesStart] = (w3 >>> 50 | w4 << 14) & 0x3FFFFFL;
        values[12 + valuesStart] = w4 >>> 8 & 0x3FFFFFL;
        values[13 + valuesStart] = w4 >>> 30 & 0x3FFFFFL;
        values[14 + valuesStart] = (w4 >>> 52 | w5 << 12) & 0x3FFFFFL;
        values[15 + valuesStart] = w5 >>> 10 & 0x3FFFFFL;
        values[16 + valuesStart] = w5 >>> 32 & 0x3FFFFFL;
        values[17 + valuesStart] = (w5 >>> 54 | w6 << 10) & 0x3FFFFFL;
        values[18 + valuesStart] = w6 >>> 12 & 0x3FFFFFL;
        values[19 + valuesStart] = w6 >>> 34 & 0x3FFFFFL;
        values[20 + valuesStart] = (w6 >>> 56 | w7 << 8) & 0x3FFFFFL;
        values[21 + valuesStart] = w7 >>> 14 & 0x3FFFFFL;
        values[22 + valuesStart] = w7 >>> 36 & 0x3FFFFFL;
        values[23 + valuesStart] = (w7 >>> 58 | w8 << 6) & 0x3FFFFFL;
        values[24 + valuesStart] = w8 >>> 16 & 0x3FFFFFL;
        values[25 + valuesStart] = w8 >>> 38 & 0x3FFFFFL;
        values[26 + valuesStart] = (w8 >>> 60 | w9 << 4) & 0x3FFFFFL;
        values[27 + valuesStart] = w9 >>> 18 & 0x3FFFFFL;
        values[28 + valuesStart] = w9 >>> 40 & 0x3FFFFFL;
        values[29 + valuesStart] = (w9 >>> 62 | w10 << 2) & 0x3FFFFFL;
        values[30 + valuesStart] = w10 >>> 20 & 0x3FFFFFL;
        values[31 + valuesStart] = w10 >>> 42;
        values[32 + valuesStart] = w11 & 0x3FFFFFL;
        values[33 + valuesStart] = w11 >>> 22 & 0x3FFFFFL;
        values[34 + valuesStart] = (w11 >>> 44 | w12 << 20) & 0x3FFFFFL;
        values[35 + valuesStart] = w12 >>> 2 & 0x3FFFFFL;
        values[36 + valuesStart] = w12 >>> 24 & 0x3FFFFFL;
        values[37 + valuesStart] = (w12 >>> 46 | w13 << 18) & 0x3FFFFFL;
        values[38 + valuesStart] = w13 >>> 4 & 0x3FFFFFL;
        values[39 + valuesStart] = w13 >>> 26 & 0x3FFFFFL;
        values[40 + valuesStart] = (w13 >>> 48 | w14 << 16) & 0x3FFFFFL;
        values[41 + valuesStart] = w14 >>> 6 & 0x3FFFFFL;
        values[42 + valuesStart] = w14 >>> 28 & 0x3FFFFFL;
        values[43 + valuesStart] = (w14 >>> 50 | w15 << 14) & 0x3FFFFFL;
        values[44 + valuesStart] = w15 >>> 8 & 0x3FFFFFL;
        values[45 + valuesStart] = w15 >>> 30 & 0x3FFFFFL;
        values[46 + valuesStart] = (w15 >>> 52 | w16 << 12) & 0x3FFFFFL;
        values[47 + valuesStart] = w16 >>> 10 & 0x3FFFFFL;
        values[48 + valuesStart] = w16 >>> 32 & 0x3FFFFFL;
        values[49 + valuesStart] = (w16 >>> 54 | w17 << 10) & 0x3FFFFFL;
        values[50 + valuesStart] = w17 >>> 12 & 0x3FFFFFL;
        values[51 + valuesStart] = w17 >>> 34 & 0x3FFFFFL;
        values[52 + valuesStart] = (w17 >>> 56 | w18 << 8) & 0x3FFFFFL;
        values[53 + valuesStart] = w18 >>> 14 & 0x3FFFFFL;
        values[54 + valuesStart] = w18 >>> 36 & 0x3FFFFFL;
        values[55 + valuesStart] = (w18 >>> 58 | w19 << 6) & 0x3FFFFFL;
        values[56 + valuesStart] = w19 >>> 16 & 0x3FFFFFL;
        values[57 + valuesStart] = w19 >>> 38 & 0x3FFFFFL;
        values[58 + valuesStart] = (w19 >>> 60 | w20 << 4) & 0x3FFFFFL;
        values[59 + valuesStart] = w20 >>> 18 & 0x3FFFFFL;
        values[60 + valuesStart] = w20 >>> 40 & 0x3FFFFFL;
        values[61 + valuesStart] = (w20 >>> 62 | w21 << 2) & 0x3FFFFFL;
        values[62 + valuesStart] = w21 >>> 20 & 0x3FFFFFL;
        values[63 + valuesStart] = w21 >>> 42;
        return 176 + packedPtr;
    }

    /**
     * Unpacks 64 23-bit values using 184 bytes, touching 23 words.
     */
    private static long unpack23(long[] values, int valuesStart, long packedPtr) {
        // Access 23 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFL;
        values[1 + valuesStart] = w0 >>> 23 & 0x7FFFFFL;
        values[2 + valuesStart] = (w0 >>> 46 | w1 << 18) & 0x7FFFFFL;
        values[3 + valuesStart] = w1 >>> 5 & 0x7FFFFFL;
        values[4 + valuesStart] = w1 >>> 28 & 0x7FFFFFL;
        values[5 + valuesStart] = (w1 >>> 51 | w2 << 13) & 0x7FFFFFL;
        values[6 + valuesStart] = w2 >>> 10 & 0x7FFFFFL;
        values[7 + valuesStart] = w2 >>> 33 & 0x7FFFFFL;
        values[8 + valuesStart] = (w2 >>> 56 | w3 << 8) & 0x7FFFFFL;
        values[9 + valuesStart] = w3 >>> 15 & 0x7FFFFFL;
        values[10 + valuesStart] = w3 >>> 38 & 0x7FFFFFL;
        values[11 + valuesStart] = (w3 >>> 61 | w4 << 3) & 0x7FFFFFL;
        values[12 + valuesStart] = w4 >>> 20 & 0x7FFFFFL;
        values[13 + valuesStart] = (w4 >>> 43 | w5 << 21) & 0x7FFFFFL;
        values[14 + valuesStart] = w5 >>> 2 & 0x7FFFFFL;
        values[15 + valuesStart] = w5 >>> 25 & 0x7FFFFFL;
        values[16 + valuesStart] = (w5 >>> 48 | w6 << 16) & 0x7FFFFFL;
        values[17 + valuesStart] = w6 >>> 7 & 0x7FFFFFL;
        values[18 + valuesStart] = w6 >>> 30 & 0x7FFFFFL;
        values[19 + valuesStart] = (w6 >>> 53 | w7 << 11) & 0x7FFFFFL;
        values[20 + valuesStart] = w7 >>> 12 & 0x7FFFFFL;
        values[21 + valuesStart] = w7 >>> 35 & 0x7FFFFFL;
        values[22 + valuesStart] = (w7 >>> 58 | w8 << 6) & 0x7FFFFFL;
        values[23 + valuesStart] = w8 >>> 17 & 0x7FFFFFL;
        values[24 + valuesStart] = w8 >>> 40 & 0x7FFFFFL;
        values[25 + valuesStart] = (w8 >>> 63 | w9 << 1) & 0x7FFFFFL;
        values[26 + valuesStart] = w9 >>> 22 & 0x7FFFFFL;
        values[27 + valuesStart] = (w9 >>> 45 | w10 << 19) & 0x7FFFFFL;
        values[28 + valuesStart] = w10 >>> 4 & 0x7FFFFFL;
        values[29 + valuesStart] = w10 >>> 27 & 0x7FFFFFL;
        values[30 + valuesStart] = (w10 >>> 50 | w11 << 14) & 0x7FFFFFL;
        values[31 + valuesStart] = w11 >>> 9 & 0x7FFFFFL;
        values[32 + valuesStart] = w11 >>> 32 & 0x7FFFFFL;
        values[33 + valuesStart] = (w11 >>> 55 | w12 << 9) & 0x7FFFFFL;
        values[34 + valuesStart] = w12 >>> 14 & 0x7FFFFFL;
        values[35 + valuesStart] = w12 >>> 37 & 0x7FFFFFL;
        values[36 + valuesStart] = (w12 >>> 60 | w13 << 4) & 0x7FFFFFL;
        values[37 + valuesStart] = w13 >>> 19 & 0x7FFFFFL;
        values[38 + valuesStart] = (w13 >>> 42 | w14 << 22) & 0x7FFFFFL;
        values[39 + valuesStart] = w14 >>> 1 & 0x7FFFFFL;
        values[40 + valuesStart] = w14 >>> 24 & 0x7FFFFFL;
        values[41 + valuesStart] = (w14 >>> 47 | w15 << 17) & 0x7FFFFFL;
        values[42 + valuesStart] = w15 >>> 6 & 0x7FFFFFL;
        values[43 + valuesStart] = w15 >>> 29 & 0x7FFFFFL;
        values[44 + valuesStart] = (w15 >>> 52 | w16 << 12) & 0x7FFFFFL;
        values[45 + valuesStart] = w16 >>> 11 & 0x7FFFFFL;
        values[46 + valuesStart] = w16 >>> 34 & 0x7FFFFFL;
        values[47 + valuesStart] = (w16 >>> 57 | w17 << 7) & 0x7FFFFFL;
        values[48 + valuesStart] = w17 >>> 16 & 0x7FFFFFL;
        values[49 + valuesStart] = w17 >>> 39 & 0x7FFFFFL;
        values[50 + valuesStart] = (w17 >>> 62 | w18 << 2) & 0x7FFFFFL;
        values[51 + valuesStart] = w18 >>> 21 & 0x7FFFFFL;
        values[52 + valuesStart] = (w18 >>> 44 | w19 << 20) & 0x7FFFFFL;
        values[53 + valuesStart] = w19 >>> 3 & 0x7FFFFFL;
        values[54 + valuesStart] = w19 >>> 26 & 0x7FFFFFL;
        values[55 + valuesStart] = (w19 >>> 49 | w20 << 15) & 0x7FFFFFL;
        values[56 + valuesStart] = w20 >>> 8 & 0x7FFFFFL;
        values[57 + valuesStart] = w20 >>> 31 & 0x7FFFFFL;
        values[58 + valuesStart] = (w20 >>> 54 | w21 << 10) & 0x7FFFFFL;
        values[59 + valuesStart] = w21 >>> 13 & 0x7FFFFFL;
        values[60 + valuesStart] = w21 >>> 36 & 0x7FFFFFL;
        values[61 + valuesStart] = (w21 >>> 59 | w22 << 5) & 0x7FFFFFL;
        values[62 + valuesStart] = w22 >>> 18 & 0x7FFFFFL;
        values[63 + valuesStart] = w22 >>> 41;
        return 184 + packedPtr;
    }

    /**
     * Unpacks 64 24-bit values using 192 bytes, touching 24 words.
     */
    private static long unpack24(long[] values, int valuesStart, long packedPtr) {
        // Access 24 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFL;
        values[1 + valuesStart] = w0 >>> 24 & 0xFFFFFFL;
        values[2 + valuesStart] = (w0 >>> 48 | w1 << 16) & 0xFFFFFFL;
        values[3 + valuesStart] = w1 >>> 8 & 0xFFFFFFL;
        values[4 + valuesStart] = w1 >>> 32 & 0xFFFFFFL;
        values[5 + valuesStart] = (w1 >>> 56 | w2 << 8) & 0xFFFFFFL;
        values[6 + valuesStart] = w2 >>> 16 & 0xFFFFFFL;
        values[7 + valuesStart] = w2 >>> 40;
        values[8 + valuesStart] = w3 & 0xFFFFFFL;
        values[9 + valuesStart] = w3 >>> 24 & 0xFFFFFFL;
        values[10 + valuesStart] = (w3 >>> 48 | w4 << 16) & 0xFFFFFFL;
        values[11 + valuesStart] = w4 >>> 8 & 0xFFFFFFL;
        values[12 + valuesStart] = w4 >>> 32 & 0xFFFFFFL;
        values[13 + valuesStart] = (w4 >>> 56 | w5 << 8) & 0xFFFFFFL;
        values[14 + valuesStart] = w5 >>> 16 & 0xFFFFFFL;
        values[15 + valuesStart] = w5 >>> 40;
        values[16 + valuesStart] = w6 & 0xFFFFFFL;
        values[17 + valuesStart] = w6 >>> 24 & 0xFFFFFFL;
        values[18 + valuesStart] = (w6 >>> 48 | w7 << 16) & 0xFFFFFFL;
        values[19 + valuesStart] = w7 >>> 8 & 0xFFFFFFL;
        values[20 + valuesStart] = w7 >>> 32 & 0xFFFFFFL;
        values[21 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0xFFFFFFL;
        values[22 + valuesStart] = w8 >>> 16 & 0xFFFFFFL;
        values[23 + valuesStart] = w8 >>> 40;
        values[24 + valuesStart] = w9 & 0xFFFFFFL;
        values[25 + valuesStart] = w9 >>> 24 & 0xFFFFFFL;
        values[26 + valuesStart] = (w9 >>> 48 | w10 << 16) & 0xFFFFFFL;
        values[27 + valuesStart] = w10 >>> 8 & 0xFFFFFFL;
        values[28 + valuesStart] = w10 >>> 32 & 0xFFFFFFL;
        values[29 + valuesStart] = (w10 >>> 56 | w11 << 8) & 0xFFFFFFL;
        values[30 + valuesStart] = w11 >>> 16 & 0xFFFFFFL;
        values[31 + valuesStart] = w11 >>> 40;
        values[32 + valuesStart] = w12 & 0xFFFFFFL;
        values[33 + valuesStart] = w12 >>> 24 & 0xFFFFFFL;
        values[34 + valuesStart] = (w12 >>> 48 | w13 << 16) & 0xFFFFFFL;
        values[35 + valuesStart] = w13 >>> 8 & 0xFFFFFFL;
        values[36 + valuesStart] = w13 >>> 32 & 0xFFFFFFL;
        values[37 + valuesStart] = (w13 >>> 56 | w14 << 8) & 0xFFFFFFL;
        values[38 + valuesStart] = w14 >>> 16 & 0xFFFFFFL;
        values[39 + valuesStart] = w14 >>> 40;
        values[40 + valuesStart] = w15 & 0xFFFFFFL;
        values[41 + valuesStart] = w15 >>> 24 & 0xFFFFFFL;
        values[42 + valuesStart] = (w15 >>> 48 | w16 << 16) & 0xFFFFFFL;
        values[43 + valuesStart] = w16 >>> 8 & 0xFFFFFFL;
        values[44 + valuesStart] = w16 >>> 32 & 0xFFFFFFL;
        values[45 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0xFFFFFFL;
        values[46 + valuesStart] = w17 >>> 16 & 0xFFFFFFL;
        values[47 + valuesStart] = w17 >>> 40;
        values[48 + valuesStart] = w18 & 0xFFFFFFL;
        values[49 + valuesStart] = w18 >>> 24 & 0xFFFFFFL;
        values[50 + valuesStart] = (w18 >>> 48 | w19 << 16) & 0xFFFFFFL;
        values[51 + valuesStart] = w19 >>> 8 & 0xFFFFFFL;
        values[52 + valuesStart] = w19 >>> 32 & 0xFFFFFFL;
        values[53 + valuesStart] = (w19 >>> 56 | w20 << 8) & 0xFFFFFFL;
        values[54 + valuesStart] = w20 >>> 16 & 0xFFFFFFL;
        values[55 + valuesStart] = w20 >>> 40;
        values[56 + valuesStart] = w21 & 0xFFFFFFL;
        values[57 + valuesStart] = w21 >>> 24 & 0xFFFFFFL;
        values[58 + valuesStart] = (w21 >>> 48 | w22 << 16) & 0xFFFFFFL;
        values[59 + valuesStart] = w22 >>> 8 & 0xFFFFFFL;
        values[60 + valuesStart] = w22 >>> 32 & 0xFFFFFFL;
        values[61 + valuesStart] = (w22 >>> 56 | w23 << 8) & 0xFFFFFFL;
        values[62 + valuesStart] = w23 >>> 16 & 0xFFFFFFL;
        values[63 + valuesStart] = w23 >>> 40;
        return 192 + packedPtr;
    }

    /**
     * Unpacks 64 25-bit values using 200 bytes, touching 25 words.
     */
    private static long unpack25(long[] values, int valuesStart, long packedPtr) {
        // Access 25 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFL;
        values[1 + valuesStart] = w0 >>> 25 & 0x1FFFFFFL;
        values[2 + valuesStart] = (w0 >>> 50 | w1 << 14) & 0x1FFFFFFL;
        values[3 + valuesStart] = w1 >>> 11 & 0x1FFFFFFL;
        values[4 + valuesStart] = w1 >>> 36 & 0x1FFFFFFL;
        values[5 + valuesStart] = (w1 >>> 61 | w2 << 3) & 0x1FFFFFFL;
        values[6 + valuesStart] = w2 >>> 22 & 0x1FFFFFFL;
        values[7 + valuesStart] = (w2 >>> 47 | w3 << 17) & 0x1FFFFFFL;
        values[8 + valuesStart] = w3 >>> 8 & 0x1FFFFFFL;
        values[9 + valuesStart] = w3 >>> 33 & 0x1FFFFFFL;
        values[10 + valuesStart] = (w3 >>> 58 | w4 << 6) & 0x1FFFFFFL;
        values[11 + valuesStart] = w4 >>> 19 & 0x1FFFFFFL;
        values[12 + valuesStart] = (w4 >>> 44 | w5 << 20) & 0x1FFFFFFL;
        values[13 + valuesStart] = w5 >>> 5 & 0x1FFFFFFL;
        values[14 + valuesStart] = w5 >>> 30 & 0x1FFFFFFL;
        values[15 + valuesStart] = (w5 >>> 55 | w6 << 9) & 0x1FFFFFFL;
        values[16 + valuesStart] = w6 >>> 16 & 0x1FFFFFFL;
        values[17 + valuesStart] = (w6 >>> 41 | w7 << 23) & 0x1FFFFFFL;
        values[18 + valuesStart] = w7 >>> 2 & 0x1FFFFFFL;
        values[19 + valuesStart] = w7 >>> 27 & 0x1FFFFFFL;
        values[20 + valuesStart] = (w7 >>> 52 | w8 << 12) & 0x1FFFFFFL;
        values[21 + valuesStart] = w8 >>> 13 & 0x1FFFFFFL;
        values[22 + valuesStart] = w8 >>> 38 & 0x1FFFFFFL;
        values[23 + valuesStart] = (w8 >>> 63 | w9 << 1) & 0x1FFFFFFL;
        values[24 + valuesStart] = w9 >>> 24 & 0x1FFFFFFL;
        values[25 + valuesStart] = (w9 >>> 49 | w10 << 15) & 0x1FFFFFFL;
        values[26 + valuesStart] = w10 >>> 10 & 0x1FFFFFFL;
        values[27 + valuesStart] = w10 >>> 35 & 0x1FFFFFFL;
        values[28 + valuesStart] = (w10 >>> 60 | w11 << 4) & 0x1FFFFFFL;
        values[29 + valuesStart] = w11 >>> 21 & 0x1FFFFFFL;
        values[30 + valuesStart] = (w11 >>> 46 | w12 << 18) & 0x1FFFFFFL;
        values[31 + valuesStart] = w12 >>> 7 & 0x1FFFFFFL;
        values[32 + valuesStart] = w12 >>> 32 & 0x1FFFFFFL;
        values[33 + valuesStart] = (w12 >>> 57 | w13 << 7) & 0x1FFFFFFL;
        values[34 + valuesStart] = w13 >>> 18 & 0x1FFFFFFL;
        values[35 + valuesStart] = (w13 >>> 43 | w14 << 21) & 0x1FFFFFFL;
        values[36 + valuesStart] = w14 >>> 4 & 0x1FFFFFFL;
        values[37 + valuesStart] = w14 >>> 29 & 0x1FFFFFFL;
        values[38 + valuesStart] = (w14 >>> 54 | w15 << 10) & 0x1FFFFFFL;
        values[39 + valuesStart] = w15 >>> 15 & 0x1FFFFFFL;
        values[40 + valuesStart] = (w15 >>> 40 | w16 << 24) & 0x1FFFFFFL;
        values[41 + valuesStart] = w16 >>> 1 & 0x1FFFFFFL;
        values[42 + valuesStart] = w16 >>> 26 & 0x1FFFFFFL;
        values[43 + valuesStart] = (w16 >>> 51 | w17 << 13) & 0x1FFFFFFL;
        values[44 + valuesStart] = w17 >>> 12 & 0x1FFFFFFL;
        values[45 + valuesStart] = w17 >>> 37 & 0x1FFFFFFL;
        values[46 + valuesStart] = (w17 >>> 62 | w18 << 2) & 0x1FFFFFFL;
        values[47 + valuesStart] = w18 >>> 23 & 0x1FFFFFFL;
        values[48 + valuesStart] = (w18 >>> 48 | w19 << 16) & 0x1FFFFFFL;
        values[49 + valuesStart] = w19 >>> 9 & 0x1FFFFFFL;
        values[50 + valuesStart] = w19 >>> 34 & 0x1FFFFFFL;
        values[51 + valuesStart] = (w19 >>> 59 | w20 << 5) & 0x1FFFFFFL;
        values[52 + valuesStart] = w20 >>> 20 & 0x1FFFFFFL;
        values[53 + valuesStart] = (w20 >>> 45 | w21 << 19) & 0x1FFFFFFL;
        values[54 + valuesStart] = w21 >>> 6 & 0x1FFFFFFL;
        values[55 + valuesStart] = w21 >>> 31 & 0x1FFFFFFL;
        values[56 + valuesStart] = (w21 >>> 56 | w22 << 8) & 0x1FFFFFFL;
        values[57 + valuesStart] = w22 >>> 17 & 0x1FFFFFFL;
        values[58 + valuesStart] = (w22 >>> 42 | w23 << 22) & 0x1FFFFFFL;
        values[59 + valuesStart] = w23 >>> 3 & 0x1FFFFFFL;
        values[60 + valuesStart] = w23 >>> 28 & 0x1FFFFFFL;
        values[61 + valuesStart] = (w23 >>> 53 | w24 << 11) & 0x1FFFFFFL;
        values[62 + valuesStart] = w24 >>> 14 & 0x1FFFFFFL;
        values[63 + valuesStart] = w24 >>> 39;
        return 200 + packedPtr;
    }

    /**
     * Unpacks 64 26-bit values using 208 bytes, touching 26 words.
     */
    private static long unpack26(long[] values, int valuesStart, long packedPtr) {
        // Access 26 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFL;
        values[1 + valuesStart] = w0 >>> 26 & 0x3FFFFFFL;
        values[2 + valuesStart] = (w0 >>> 52 | w1 << 12) & 0x3FFFFFFL;
        values[3 + valuesStart] = w1 >>> 14 & 0x3FFFFFFL;
        values[4 + valuesStart] = (w1 >>> 40 | w2 << 24) & 0x3FFFFFFL;
        values[5 + valuesStart] = w2 >>> 2 & 0x3FFFFFFL;
        values[6 + valuesStart] = w2 >>> 28 & 0x3FFFFFFL;
        values[7 + valuesStart] = (w2 >>> 54 | w3 << 10) & 0x3FFFFFFL;
        values[8 + valuesStart] = w3 >>> 16 & 0x3FFFFFFL;
        values[9 + valuesStart] = (w3 >>> 42 | w4 << 22) & 0x3FFFFFFL;
        values[10 + valuesStart] = w4 >>> 4 & 0x3FFFFFFL;
        values[11 + valuesStart] = w4 >>> 30 & 0x3FFFFFFL;
        values[12 + valuesStart] = (w4 >>> 56 | w5 << 8) & 0x3FFFFFFL;
        values[13 + valuesStart] = w5 >>> 18 & 0x3FFFFFFL;
        values[14 + valuesStart] = (w5 >>> 44 | w6 << 20) & 0x3FFFFFFL;
        values[15 + valuesStart] = w6 >>> 6 & 0x3FFFFFFL;
        values[16 + valuesStart] = w6 >>> 32 & 0x3FFFFFFL;
        values[17 + valuesStart] = (w6 >>> 58 | w7 << 6) & 0x3FFFFFFL;
        values[18 + valuesStart] = w7 >>> 20 & 0x3FFFFFFL;
        values[19 + valuesStart] = (w7 >>> 46 | w8 << 18) & 0x3FFFFFFL;
        values[20 + valuesStart] = w8 >>> 8 & 0x3FFFFFFL;
        values[21 + valuesStart] = w8 >>> 34 & 0x3FFFFFFL;
        values[22 + valuesStart] = (w8 >>> 60 | w9 << 4) & 0x3FFFFFFL;
        values[23 + valuesStart] = w9 >>> 22 & 0x3FFFFFFL;
        values[24 + valuesStart] = (w9 >>> 48 | w10 << 16) & 0x3FFFFFFL;
        values[25 + valuesStart] = w10 >>> 10 & 0x3FFFFFFL;
        values[26 + valuesStart] = w10 >>> 36 & 0x3FFFFFFL;
        values[27 + valuesStart] = (w10 >>> 62 | w11 << 2) & 0x3FFFFFFL;
        values[28 + valuesStart] = w11 >>> 24 & 0x3FFFFFFL;
        values[29 + valuesStart] = (w11 >>> 50 | w12 << 14) & 0x3FFFFFFL;
        values[30 + valuesStart] = w12 >>> 12 & 0x3FFFFFFL;
        values[31 + valuesStart] = w12 >>> 38;
        values[32 + valuesStart] = w13 & 0x3FFFFFFL;
        values[33 + valuesStart] = w13 >>> 26 & 0x3FFFFFFL;
        values[34 + valuesStart] = (w13 >>> 52 | w14 << 12) & 0x3FFFFFFL;
        values[35 + valuesStart] = w14 >>> 14 & 0x3FFFFFFL;
        values[36 + valuesStart] = (w14 >>> 40 | w15 << 24) & 0x3FFFFFFL;
        values[37 + valuesStart] = w15 >>> 2 & 0x3FFFFFFL;
        values[38 + valuesStart] = w15 >>> 28 & 0x3FFFFFFL;
        values[39 + valuesStart] = (w15 >>> 54 | w16 << 10) & 0x3FFFFFFL;
        values[40 + valuesStart] = w16 >>> 16 & 0x3FFFFFFL;
        values[41 + valuesStart] = (w16 >>> 42 | w17 << 22) & 0x3FFFFFFL;
        values[42 + valuesStart] = w17 >>> 4 & 0x3FFFFFFL;
        values[43 + valuesStart] = w17 >>> 30 & 0x3FFFFFFL;
        values[44 + valuesStart] = (w17 >>> 56 | w18 << 8) & 0x3FFFFFFL;
        values[45 + valuesStart] = w18 >>> 18 & 0x3FFFFFFL;
        values[46 + valuesStart] = (w18 >>> 44 | w19 << 20) & 0x3FFFFFFL;
        values[47 + valuesStart] = w19 >>> 6 & 0x3FFFFFFL;
        values[48 + valuesStart] = w19 >>> 32 & 0x3FFFFFFL;
        values[49 + valuesStart] = (w19 >>> 58 | w20 << 6) & 0x3FFFFFFL;
        values[50 + valuesStart] = w20 >>> 20 & 0x3FFFFFFL;
        values[51 + valuesStart] = (w20 >>> 46 | w21 << 18) & 0x3FFFFFFL;
        values[52 + valuesStart] = w21 >>> 8 & 0x3FFFFFFL;
        values[53 + valuesStart] = w21 >>> 34 & 0x3FFFFFFL;
        values[54 + valuesStart] = (w21 >>> 60 | w22 << 4) & 0x3FFFFFFL;
        values[55 + valuesStart] = w22 >>> 22 & 0x3FFFFFFL;
        values[56 + valuesStart] = (w22 >>> 48 | w23 << 16) & 0x3FFFFFFL;
        values[57 + valuesStart] = w23 >>> 10 & 0x3FFFFFFL;
        values[58 + valuesStart] = w23 >>> 36 & 0x3FFFFFFL;
        values[59 + valuesStart] = (w23 >>> 62 | w24 << 2) & 0x3FFFFFFL;
        values[60 + valuesStart] = w24 >>> 24 & 0x3FFFFFFL;
        values[61 + valuesStart] = (w24 >>> 50 | w25 << 14) & 0x3FFFFFFL;
        values[62 + valuesStart] = w25 >>> 12 & 0x3FFFFFFL;
        values[63 + valuesStart] = w25 >>> 38;
        return 208 + packedPtr;
    }

    /**
     * Unpacks 64 27-bit values using 216 bytes, touching 27 words.
     */
    private static long unpack27(long[] values, int valuesStart, long packedPtr) {
        // Access 27 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFL;
        values[1 + valuesStart] = w0 >>> 27 & 0x7FFFFFFL;
        values[2 + valuesStart] = (w0 >>> 54 | w1 << 10) & 0x7FFFFFFL;
        values[3 + valuesStart] = w1 >>> 17 & 0x7FFFFFFL;
        values[4 + valuesStart] = (w1 >>> 44 | w2 << 20) & 0x7FFFFFFL;
        values[5 + valuesStart] = w2 >>> 7 & 0x7FFFFFFL;
        values[6 + valuesStart] = w2 >>> 34 & 0x7FFFFFFL;
        values[7 + valuesStart] = (w2 >>> 61 | w3 << 3) & 0x7FFFFFFL;
        values[8 + valuesStart] = w3 >>> 24 & 0x7FFFFFFL;
        values[9 + valuesStart] = (w3 >>> 51 | w4 << 13) & 0x7FFFFFFL;
        values[10 + valuesStart] = w4 >>> 14 & 0x7FFFFFFL;
        values[11 + valuesStart] = (w4 >>> 41 | w5 << 23) & 0x7FFFFFFL;
        values[12 + valuesStart] = w5 >>> 4 & 0x7FFFFFFL;
        values[13 + valuesStart] = w5 >>> 31 & 0x7FFFFFFL;
        values[14 + valuesStart] = (w5 >>> 58 | w6 << 6) & 0x7FFFFFFL;
        values[15 + valuesStart] = w6 >>> 21 & 0x7FFFFFFL;
        values[16 + valuesStart] = (w6 >>> 48 | w7 << 16) & 0x7FFFFFFL;
        values[17 + valuesStart] = w7 >>> 11 & 0x7FFFFFFL;
        values[18 + valuesStart] = (w7 >>> 38 | w8 << 26) & 0x7FFFFFFL;
        values[19 + valuesStart] = w8 >>> 1 & 0x7FFFFFFL;
        values[20 + valuesStart] = w8 >>> 28 & 0x7FFFFFFL;
        values[21 + valuesStart] = (w8 >>> 55 | w9 << 9) & 0x7FFFFFFL;
        values[22 + valuesStart] = w9 >>> 18 & 0x7FFFFFFL;
        values[23 + valuesStart] = (w9 >>> 45 | w10 << 19) & 0x7FFFFFFL;
        values[24 + valuesStart] = w10 >>> 8 & 0x7FFFFFFL;
        values[25 + valuesStart] = w10 >>> 35 & 0x7FFFFFFL;
        values[26 + valuesStart] = (w10 >>> 62 | w11 << 2) & 0x7FFFFFFL;
        values[27 + valuesStart] = w11 >>> 25 & 0x7FFFFFFL;
        values[28 + valuesStart] = (w11 >>> 52 | w12 << 12) & 0x7FFFFFFL;
        values[29 + valuesStart] = w12 >>> 15 & 0x7FFFFFFL;
        values[30 + valuesStart] = (w12 >>> 42 | w13 << 22) & 0x7FFFFFFL;
        values[31 + valuesStart] = w13 >>> 5 & 0x7FFFFFFL;
        values[32 + valuesStart] = w13 >>> 32 & 0x7FFFFFFL;
        values[33 + valuesStart] = (w13 >>> 59 | w14 << 5) & 0x7FFFFFFL;
        values[34 + valuesStart] = w14 >>> 22 & 0x7FFFFFFL;
        values[35 + valuesStart] = (w14 >>> 49 | w15 << 15) & 0x7FFFFFFL;
        values[36 + valuesStart] = w15 >>> 12 & 0x7FFFFFFL;
        values[37 + valuesStart] = (w15 >>> 39 | w16 << 25) & 0x7FFFFFFL;
        values[38 + valuesStart] = w16 >>> 2 & 0x7FFFFFFL;
        values[39 + valuesStart] = w16 >>> 29 & 0x7FFFFFFL;
        values[40 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0x7FFFFFFL;
        values[41 + valuesStart] = w17 >>> 19 & 0x7FFFFFFL;
        values[42 + valuesStart] = (w17 >>> 46 | w18 << 18) & 0x7FFFFFFL;
        values[43 + valuesStart] = w18 >>> 9 & 0x7FFFFFFL;
        values[44 + valuesStart] = w18 >>> 36 & 0x7FFFFFFL;
        values[45 + valuesStart] = (w18 >>> 63 | w19 << 1) & 0x7FFFFFFL;
        values[46 + valuesStart] = w19 >>> 26 & 0x7FFFFFFL;
        values[47 + valuesStart] = (w19 >>> 53 | w20 << 11) & 0x7FFFFFFL;
        values[48 + valuesStart] = w20 >>> 16 & 0x7FFFFFFL;
        values[49 + valuesStart] = (w20 >>> 43 | w21 << 21) & 0x7FFFFFFL;
        values[50 + valuesStart] = w21 >>> 6 & 0x7FFFFFFL;
        values[51 + valuesStart] = w21 >>> 33 & 0x7FFFFFFL;
        values[52 + valuesStart] = (w21 >>> 60 | w22 << 4) & 0x7FFFFFFL;
        values[53 + valuesStart] = w22 >>> 23 & 0x7FFFFFFL;
        values[54 + valuesStart] = (w22 >>> 50 | w23 << 14) & 0x7FFFFFFL;
        values[55 + valuesStart] = w23 >>> 13 & 0x7FFFFFFL;
        values[56 + valuesStart] = (w23 >>> 40 | w24 << 24) & 0x7FFFFFFL;
        values[57 + valuesStart] = w24 >>> 3 & 0x7FFFFFFL;
        values[58 + valuesStart] = w24 >>> 30 & 0x7FFFFFFL;
        values[59 + valuesStart] = (w24 >>> 57 | w25 << 7) & 0x7FFFFFFL;
        values[60 + valuesStart] = w25 >>> 20 & 0x7FFFFFFL;
        values[61 + valuesStart] = (w25 >>> 47 | w26 << 17) & 0x7FFFFFFL;
        values[62 + valuesStart] = w26 >>> 10 & 0x7FFFFFFL;
        values[63 + valuesStart] = w26 >>> 37;
        return 216 + packedPtr;
    }

    /**
     * Unpacks 64 28-bit values using 224 bytes, touching 28 words.
     */
    private static long unpack28(long[] values, int valuesStart, long packedPtr) {
        // Access 28 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFFL;
        values[1 + valuesStart] = w0 >>> 28 & 0xFFFFFFFL;
        values[2 + valuesStart] = (w0 >>> 56 | w1 << 8) & 0xFFFFFFFL;
        values[3 + valuesStart] = w1 >>> 20 & 0xFFFFFFFL;
        values[4 + valuesStart] = (w1 >>> 48 | w2 << 16) & 0xFFFFFFFL;
        values[5 + valuesStart] = w2 >>> 12 & 0xFFFFFFFL;
        values[6 + valuesStart] = (w2 >>> 40 | w3 << 24) & 0xFFFFFFFL;
        values[7 + valuesStart] = w3 >>> 4 & 0xFFFFFFFL;
        values[8 + valuesStart] = w3 >>> 32 & 0xFFFFFFFL;
        values[9 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0xFFFFFFFL;
        values[10 + valuesStart] = w4 >>> 24 & 0xFFFFFFFL;
        values[11 + valuesStart] = (w4 >>> 52 | w5 << 12) & 0xFFFFFFFL;
        values[12 + valuesStart] = w5 >>> 16 & 0xFFFFFFFL;
        values[13 + valuesStart] = (w5 >>> 44 | w6 << 20) & 0xFFFFFFFL;
        values[14 + valuesStart] = w6 >>> 8 & 0xFFFFFFFL;
        values[15 + valuesStart] = w6 >>> 36;
        values[16 + valuesStart] = w7 & 0xFFFFFFFL;
        values[17 + valuesStart] = w7 >>> 28 & 0xFFFFFFFL;
        values[18 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0xFFFFFFFL;
        values[19 + valuesStart] = w8 >>> 20 & 0xFFFFFFFL;
        values[20 + valuesStart] = (w8 >>> 48 | w9 << 16) & 0xFFFFFFFL;
        values[21 + valuesStart] = w9 >>> 12 & 0xFFFFFFFL;
        values[22 + valuesStart] = (w9 >>> 40 | w10 << 24) & 0xFFFFFFFL;
        values[23 + valuesStart] = w10 >>> 4 & 0xFFFFFFFL;
        values[24 + valuesStart] = w10 >>> 32 & 0xFFFFFFFL;
        values[25 + valuesStart] = (w10 >>> 60 | w11 << 4) & 0xFFFFFFFL;
        values[26 + valuesStart] = w11 >>> 24 & 0xFFFFFFFL;
        values[27 + valuesStart] = (w11 >>> 52 | w12 << 12) & 0xFFFFFFFL;
        values[28 + valuesStart] = w12 >>> 16 & 0xFFFFFFFL;
        values[29 + valuesStart] = (w12 >>> 44 | w13 << 20) & 0xFFFFFFFL;
        values[30 + valuesStart] = w13 >>> 8 & 0xFFFFFFFL;
        values[31 + valuesStart] = w13 >>> 36;
        values[32 + valuesStart] = w14 & 0xFFFFFFFL;
        values[33 + valuesStart] = w14 >>> 28 & 0xFFFFFFFL;
        values[34 + valuesStart] = (w14 >>> 56 | w15 << 8) & 0xFFFFFFFL;
        values[35 + valuesStart] = w15 >>> 20 & 0xFFFFFFFL;
        values[36 + valuesStart] = (w15 >>> 48 | w16 << 16) & 0xFFFFFFFL;
        values[37 + valuesStart] = w16 >>> 12 & 0xFFFFFFFL;
        values[38 + valuesStart] = (w16 >>> 40 | w17 << 24) & 0xFFFFFFFL;
        values[39 + valuesStart] = w17 >>> 4 & 0xFFFFFFFL;
        values[40 + valuesStart] = w17 >>> 32 & 0xFFFFFFFL;
        values[41 + valuesStart] = (w17 >>> 60 | w18 << 4) & 0xFFFFFFFL;
        values[42 + valuesStart] = w18 >>> 24 & 0xFFFFFFFL;
        values[43 + valuesStart] = (w18 >>> 52 | w19 << 12) & 0xFFFFFFFL;
        values[44 + valuesStart] = w19 >>> 16 & 0xFFFFFFFL;
        values[45 + valuesStart] = (w19 >>> 44 | w20 << 20) & 0xFFFFFFFL;
        values[46 + valuesStart] = w20 >>> 8 & 0xFFFFFFFL;
        values[47 + valuesStart] = w20 >>> 36;
        values[48 + valuesStart] = w21 & 0xFFFFFFFL;
        values[49 + valuesStart] = w21 >>> 28 & 0xFFFFFFFL;
        values[50 + valuesStart] = (w21 >>> 56 | w22 << 8) & 0xFFFFFFFL;
        values[51 + valuesStart] = w22 >>> 20 & 0xFFFFFFFL;
        values[52 + valuesStart] = (w22 >>> 48 | w23 << 16) & 0xFFFFFFFL;
        values[53 + valuesStart] = w23 >>> 12 & 0xFFFFFFFL;
        values[54 + valuesStart] = (w23 >>> 40 | w24 << 24) & 0xFFFFFFFL;
        values[55 + valuesStart] = w24 >>> 4 & 0xFFFFFFFL;
        values[56 + valuesStart] = w24 >>> 32 & 0xFFFFFFFL;
        values[57 + valuesStart] = (w24 >>> 60 | w25 << 4) & 0xFFFFFFFL;
        values[58 + valuesStart] = w25 >>> 24 & 0xFFFFFFFL;
        values[59 + valuesStart] = (w25 >>> 52 | w26 << 12) & 0xFFFFFFFL;
        values[60 + valuesStart] = w26 >>> 16 & 0xFFFFFFFL;
        values[61 + valuesStart] = (w26 >>> 44 | w27 << 20) & 0xFFFFFFFL;
        values[62 + valuesStart] = w27 >>> 8 & 0xFFFFFFFL;
        values[63 + valuesStart] = w27 >>> 36;
        return 224 + packedPtr;
    }

    /**
     * Unpacks 64 29-bit values using 232 bytes, touching 29 words.
     */
    private static long unpack29(long[] values, int valuesStart, long packedPtr) {
        // Access 29 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFFL;
        values[1 + valuesStart] = w0 >>> 29 & 0x1FFFFFFFL;
        values[2 + valuesStart] = (w0 >>> 58 | w1 << 6) & 0x1FFFFFFFL;
        values[3 + valuesStart] = w1 >>> 23 & 0x1FFFFFFFL;
        values[4 + valuesStart] = (w1 >>> 52 | w2 << 12) & 0x1FFFFFFFL;
        values[5 + valuesStart] = w2 >>> 17 & 0x1FFFFFFFL;
        values[6 + valuesStart] = (w2 >>> 46 | w3 << 18) & 0x1FFFFFFFL;
        values[7 + valuesStart] = w3 >>> 11 & 0x1FFFFFFFL;
        values[8 + valuesStart] = (w3 >>> 40 | w4 << 24) & 0x1FFFFFFFL;
        values[9 + valuesStart] = w4 >>> 5 & 0x1FFFFFFFL;
        values[10 + valuesStart] = w4 >>> 34 & 0x1FFFFFFFL;
        values[11 + valuesStart] = (w4 >>> 63 | w5 << 1) & 0x1FFFFFFFL;
        values[12 + valuesStart] = w5 >>> 28 & 0x1FFFFFFFL;
        values[13 + valuesStart] = (w5 >>> 57 | w6 << 7) & 0x1FFFFFFFL;
        values[14 + valuesStart] = w6 >>> 22 & 0x1FFFFFFFL;
        values[15 + valuesStart] = (w6 >>> 51 | w7 << 13) & 0x1FFFFFFFL;
        values[16 + valuesStart] = w7 >>> 16 & 0x1FFFFFFFL;
        values[17 + valuesStart] = (w7 >>> 45 | w8 << 19) & 0x1FFFFFFFL;
        values[18 + valuesStart] = w8 >>> 10 & 0x1FFFFFFFL;
        values[19 + valuesStart] = (w8 >>> 39 | w9 << 25) & 0x1FFFFFFFL;
        values[20 + valuesStart] = w9 >>> 4 & 0x1FFFFFFFL;
        values[21 + valuesStart] = w9 >>> 33 & 0x1FFFFFFFL;
        values[22 + valuesStart] = (w9 >>> 62 | w10 << 2) & 0x1FFFFFFFL;
        values[23 + valuesStart] = w10 >>> 27 & 0x1FFFFFFFL;
        values[24 + valuesStart] = (w10 >>> 56 | w11 << 8) & 0x1FFFFFFFL;
        values[25 + valuesStart] = w11 >>> 21 & 0x1FFFFFFFL;
        values[26 + valuesStart] = (w11 >>> 50 | w12 << 14) & 0x1FFFFFFFL;
        values[27 + valuesStart] = w12 >>> 15 & 0x1FFFFFFFL;
        values[28 + valuesStart] = (w12 >>> 44 | w13 << 20) & 0x1FFFFFFFL;
        values[29 + valuesStart] = w13 >>> 9 & 0x1FFFFFFFL;
        values[30 + valuesStart] = (w13 >>> 38 | w14 << 26) & 0x1FFFFFFFL;
        values[31 + valuesStart] = w14 >>> 3 & 0x1FFFFFFFL;
        values[32 + valuesStart] = w14 >>> 32 & 0x1FFFFFFFL;
        values[33 + valuesStart] = (w14 >>> 61 | w15 << 3) & 0x1FFFFFFFL;
        values[34 + valuesStart] = w15 >>> 26 & 0x1FFFFFFFL;
        values[35 + valuesStart] = (w15 >>> 55 | w16 << 9) & 0x1FFFFFFFL;
        values[36 + valuesStart] = w16 >>> 20 & 0x1FFFFFFFL;
        values[37 + valuesStart] = (w16 >>> 49 | w17 << 15) & 0x1FFFFFFFL;
        values[38 + valuesStart] = w17 >>> 14 & 0x1FFFFFFFL;
        values[39 + valuesStart] = (w17 >>> 43 | w18 << 21) & 0x1FFFFFFFL;
        values[40 + valuesStart] = w18 >>> 8 & 0x1FFFFFFFL;
        values[41 + valuesStart] = (w18 >>> 37 | w19 << 27) & 0x1FFFFFFFL;
        values[42 + valuesStart] = w19 >>> 2 & 0x1FFFFFFFL;
        values[43 + valuesStart] = w19 >>> 31 & 0x1FFFFFFFL;
        values[44 + valuesStart] = (w19 >>> 60 | w20 << 4) & 0x1FFFFFFFL;
        values[45 + valuesStart] = w20 >>> 25 & 0x1FFFFFFFL;
        values[46 + valuesStart] = (w20 >>> 54 | w21 << 10) & 0x1FFFFFFFL;
        values[47 + valuesStart] = w21 >>> 19 & 0x1FFFFFFFL;
        values[48 + valuesStart] = (w21 >>> 48 | w22 << 16) & 0x1FFFFFFFL;
        values[49 + valuesStart] = w22 >>> 13 & 0x1FFFFFFFL;
        values[50 + valuesStart] = (w22 >>> 42 | w23 << 22) & 0x1FFFFFFFL;
        values[51 + valuesStart] = w23 >>> 7 & 0x1FFFFFFFL;
        values[52 + valuesStart] = (w23 >>> 36 | w24 << 28) & 0x1FFFFFFFL;
        values[53 + valuesStart] = w24 >>> 1 & 0x1FFFFFFFL;
        values[54 + valuesStart] = w24 >>> 30 & 0x1FFFFFFFL;
        values[55 + valuesStart] = (w24 >>> 59 | w25 << 5) & 0x1FFFFFFFL;
        values[56 + valuesStart] = w25 >>> 24 & 0x1FFFFFFFL;
        values[57 + valuesStart] = (w25 >>> 53 | w26 << 11) & 0x1FFFFFFFL;
        values[58 + valuesStart] = w26 >>> 18 & 0x1FFFFFFFL;
        values[59 + valuesStart] = (w26 >>> 47 | w27 << 17) & 0x1FFFFFFFL;
        values[60 + valuesStart] = w27 >>> 12 & 0x1FFFFFFFL;
        values[61 + valuesStart] = (w27 >>> 41 | w28 << 23) & 0x1FFFFFFFL;
        values[62 + valuesStart] = w28 >>> 6 & 0x1FFFFFFFL;
        values[63 + valuesStart] = w28 >>> 35;
        return 232 + packedPtr;
    }

    /**
     * Unpacks 64 30-bit values using 240 bytes, touching 30 words.
     */
    private static long unpack30(long[] values, int valuesStart, long packedPtr) {
        // Access 30 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFFL;
        values[1 + valuesStart] = w0 >>> 30 & 0x3FFFFFFFL;
        values[2 + valuesStart] = (w0 >>> 60 | w1 << 4) & 0x3FFFFFFFL;
        values[3 + valuesStart] = w1 >>> 26 & 0x3FFFFFFFL;
        values[4 + valuesStart] = (w1 >>> 56 | w2 << 8) & 0x3FFFFFFFL;
        values[5 + valuesStart] = w2 >>> 22 & 0x3FFFFFFFL;
        values[6 + valuesStart] = (w2 >>> 52 | w3 << 12) & 0x3FFFFFFFL;
        values[7 + valuesStart] = w3 >>> 18 & 0x3FFFFFFFL;
        values[8 + valuesStart] = (w3 >>> 48 | w4 << 16) & 0x3FFFFFFFL;
        values[9 + valuesStart] = w4 >>> 14 & 0x3FFFFFFFL;
        values[10 + valuesStart] = (w4 >>> 44 | w5 << 20) & 0x3FFFFFFFL;
        values[11 + valuesStart] = w5 >>> 10 & 0x3FFFFFFFL;
        values[12 + valuesStart] = (w5 >>> 40 | w6 << 24) & 0x3FFFFFFFL;
        values[13 + valuesStart] = w6 >>> 6 & 0x3FFFFFFFL;
        values[14 + valuesStart] = (w6 >>> 36 | w7 << 28) & 0x3FFFFFFFL;
        values[15 + valuesStart] = w7 >>> 2 & 0x3FFFFFFFL;
        values[16 + valuesStart] = w7 >>> 32 & 0x3FFFFFFFL;
        values[17 + valuesStart] = (w7 >>> 62 | w8 << 2) & 0x3FFFFFFFL;
        values[18 + valuesStart] = w8 >>> 28 & 0x3FFFFFFFL;
        values[19 + valuesStart] = (w8 >>> 58 | w9 << 6) & 0x3FFFFFFFL;
        values[20 + valuesStart] = w9 >>> 24 & 0x3FFFFFFFL;
        values[21 + valuesStart] = (w9 >>> 54 | w10 << 10) & 0x3FFFFFFFL;
        values[22 + valuesStart] = w10 >>> 20 & 0x3FFFFFFFL;
        values[23 + valuesStart] = (w10 >>> 50 | w11 << 14) & 0x3FFFFFFFL;
        values[24 + valuesStart] = w11 >>> 16 & 0x3FFFFFFFL;
        values[25 + valuesStart] = (w11 >>> 46 | w12 << 18) & 0x3FFFFFFFL;
        values[26 + valuesStart] = w12 >>> 12 & 0x3FFFFFFFL;
        values[27 + valuesStart] = (w12 >>> 42 | w13 << 22) & 0x3FFFFFFFL;
        values[28 + valuesStart] = w13 >>> 8 & 0x3FFFFFFFL;
        values[29 + valuesStart] = (w13 >>> 38 | w14 << 26) & 0x3FFFFFFFL;
        values[30 + valuesStart] = w14 >>> 4 & 0x3FFFFFFFL;
        values[31 + valuesStart] = w14 >>> 34;
        values[32 + valuesStart] = w15 & 0x3FFFFFFFL;
        values[33 + valuesStart] = w15 >>> 30 & 0x3FFFFFFFL;
        values[34 + valuesStart] = (w15 >>> 60 | w16 << 4) & 0x3FFFFFFFL;
        values[35 + valuesStart] = w16 >>> 26 & 0x3FFFFFFFL;
        values[36 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0x3FFFFFFFL;
        values[37 + valuesStart] = w17 >>> 22 & 0x3FFFFFFFL;
        values[38 + valuesStart] = (w17 >>> 52 | w18 << 12) & 0x3FFFFFFFL;
        values[39 + valuesStart] = w18 >>> 18 & 0x3FFFFFFFL;
        values[40 + valuesStart] = (w18 >>> 48 | w19 << 16) & 0x3FFFFFFFL;
        values[41 + valuesStart] = w19 >>> 14 & 0x3FFFFFFFL;
        values[42 + valuesStart] = (w19 >>> 44 | w20 << 20) & 0x3FFFFFFFL;
        values[43 + valuesStart] = w20 >>> 10 & 0x3FFFFFFFL;
        values[44 + valuesStart] = (w20 >>> 40 | w21 << 24) & 0x3FFFFFFFL;
        values[45 + valuesStart] = w21 >>> 6 & 0x3FFFFFFFL;
        values[46 + valuesStart] = (w21 >>> 36 | w22 << 28) & 0x3FFFFFFFL;
        values[47 + valuesStart] = w22 >>> 2 & 0x3FFFFFFFL;
        values[48 + valuesStart] = w22 >>> 32 & 0x3FFFFFFFL;
        values[49 + valuesStart] = (w22 >>> 62 | w23 << 2) & 0x3FFFFFFFL;
        values[50 + valuesStart] = w23 >>> 28 & 0x3FFFFFFFL;
        values[51 + valuesStart] = (w23 >>> 58 | w24 << 6) & 0x3FFFFFFFL;
        values[52 + valuesStart] = w24 >>> 24 & 0x3FFFFFFFL;
        values[53 + valuesStart] = (w24 >>> 54 | w25 << 10) & 0x3FFFFFFFL;
        values[54 + valuesStart] = w25 >>> 20 & 0x3FFFFFFFL;
        values[55 + valuesStart] = (w25 >>> 50 | w26 << 14) & 0x3FFFFFFFL;
        values[56 + valuesStart] = w26 >>> 16 & 0x3FFFFFFFL;
        values[57 + valuesStart] = (w26 >>> 46 | w27 << 18) & 0x3FFFFFFFL;
        values[58 + valuesStart] = w27 >>> 12 & 0x3FFFFFFFL;
        values[59 + valuesStart] = (w27 >>> 42 | w28 << 22) & 0x3FFFFFFFL;
        values[60 + valuesStart] = w28 >>> 8 & 0x3FFFFFFFL;
        values[61 + valuesStart] = (w28 >>> 38 | w29 << 26) & 0x3FFFFFFFL;
        values[62 + valuesStart] = w29 >>> 4 & 0x3FFFFFFFL;
        values[63 + valuesStart] = w29 >>> 34;
        return 240 + packedPtr;
    }

    /**
     * Unpacks 64 31-bit values using 248 bytes, touching 31 words.
     */
    private static long unpack31(long[] values, int valuesStart, long packedPtr) {
        // Access 31 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFFL;
        values[1 + valuesStart] = w0 >>> 31 & 0x7FFFFFFFL;
        values[2 + valuesStart] = (w0 >>> 62 | w1 << 2) & 0x7FFFFFFFL;
        values[3 + valuesStart] = w1 >>> 29 & 0x7FFFFFFFL;
        values[4 + valuesStart] = (w1 >>> 60 | w2 << 4) & 0x7FFFFFFFL;
        values[5 + valuesStart] = w2 >>> 27 & 0x7FFFFFFFL;
        values[6 + valuesStart] = (w2 >>> 58 | w3 << 6) & 0x7FFFFFFFL;
        values[7 + valuesStart] = w3 >>> 25 & 0x7FFFFFFFL;
        values[8 + valuesStart] = (w3 >>> 56 | w4 << 8) & 0x7FFFFFFFL;
        values[9 + valuesStart] = w4 >>> 23 & 0x7FFFFFFFL;
        values[10 + valuesStart] = (w4 >>> 54 | w5 << 10) & 0x7FFFFFFFL;
        values[11 + valuesStart] = w5 >>> 21 & 0x7FFFFFFFL;
        values[12 + valuesStart] = (w5 >>> 52 | w6 << 12) & 0x7FFFFFFFL;
        values[13 + valuesStart] = w6 >>> 19 & 0x7FFFFFFFL;
        values[14 + valuesStart] = (w6 >>> 50 | w7 << 14) & 0x7FFFFFFFL;
        values[15 + valuesStart] = w7 >>> 17 & 0x7FFFFFFFL;
        values[16 + valuesStart] = (w7 >>> 48 | w8 << 16) & 0x7FFFFFFFL;
        values[17 + valuesStart] = w8 >>> 15 & 0x7FFFFFFFL;
        values[18 + valuesStart] = (w8 >>> 46 | w9 << 18) & 0x7FFFFFFFL;
        values[19 + valuesStart] = w9 >>> 13 & 0x7FFFFFFFL;
        values[20 + valuesStart] = (w9 >>> 44 | w10 << 20) & 0x7FFFFFFFL;
        values[21 + valuesStart] = w10 >>> 11 & 0x7FFFFFFFL;
        values[22 + valuesStart] = (w10 >>> 42 | w11 << 22) & 0x7FFFFFFFL;
        values[23 + valuesStart] = w11 >>> 9 & 0x7FFFFFFFL;
        values[24 + valuesStart] = (w11 >>> 40 | w12 << 24) & 0x7FFFFFFFL;
        values[25 + valuesStart] = w12 >>> 7 & 0x7FFFFFFFL;
        values[26 + valuesStart] = (w12 >>> 38 | w13 << 26) & 0x7FFFFFFFL;
        values[27 + valuesStart] = w13 >>> 5 & 0x7FFFFFFFL;
        values[28 + valuesStart] = (w13 >>> 36 | w14 << 28) & 0x7FFFFFFFL;
        values[29 + valuesStart] = w14 >>> 3 & 0x7FFFFFFFL;
        values[30 + valuesStart] = (w14 >>> 34 | w15 << 30) & 0x7FFFFFFFL;
        values[31 + valuesStart] = w15 >>> 1 & 0x7FFFFFFFL;
        values[32 + valuesStart] = w15 >>> 32 & 0x7FFFFFFFL;
        values[33 + valuesStart] = (w15 >>> 63 | w16 << 1) & 0x7FFFFFFFL;
        values[34 + valuesStart] = w16 >>> 30 & 0x7FFFFFFFL;
        values[35 + valuesStart] = (w16 >>> 61 | w17 << 3) & 0x7FFFFFFFL;
        values[36 + valuesStart] = w17 >>> 28 & 0x7FFFFFFFL;
        values[37 + valuesStart] = (w17 >>> 59 | w18 << 5) & 0x7FFFFFFFL;
        values[38 + valuesStart] = w18 >>> 26 & 0x7FFFFFFFL;
        values[39 + valuesStart] = (w18 >>> 57 | w19 << 7) & 0x7FFFFFFFL;
        values[40 + valuesStart] = w19 >>> 24 & 0x7FFFFFFFL;
        values[41 + valuesStart] = (w19 >>> 55 | w20 << 9) & 0x7FFFFFFFL;
        values[42 + valuesStart] = w20 >>> 22 & 0x7FFFFFFFL;
        values[43 + valuesStart] = (w20 >>> 53 | w21 << 11) & 0x7FFFFFFFL;
        values[44 + valuesStart] = w21 >>> 20 & 0x7FFFFFFFL;
        values[45 + valuesStart] = (w21 >>> 51 | w22 << 13) & 0x7FFFFFFFL;
        values[46 + valuesStart] = w22 >>> 18 & 0x7FFFFFFFL;
        values[47 + valuesStart] = (w22 >>> 49 | w23 << 15) & 0x7FFFFFFFL;
        values[48 + valuesStart] = w23 >>> 16 & 0x7FFFFFFFL;
        values[49 + valuesStart] = (w23 >>> 47 | w24 << 17) & 0x7FFFFFFFL;
        values[50 + valuesStart] = w24 >>> 14 & 0x7FFFFFFFL;
        values[51 + valuesStart] = (w24 >>> 45 | w25 << 19) & 0x7FFFFFFFL;
        values[52 + valuesStart] = w25 >>> 12 & 0x7FFFFFFFL;
        values[53 + valuesStart] = (w25 >>> 43 | w26 << 21) & 0x7FFFFFFFL;
        values[54 + valuesStart] = w26 >>> 10 & 0x7FFFFFFFL;
        values[55 + valuesStart] = (w26 >>> 41 | w27 << 23) & 0x7FFFFFFFL;
        values[56 + valuesStart] = w27 >>> 8 & 0x7FFFFFFFL;
        values[57 + valuesStart] = (w27 >>> 39 | w28 << 25) & 0x7FFFFFFFL;
        values[58 + valuesStart] = w28 >>> 6 & 0x7FFFFFFFL;
        values[59 + valuesStart] = (w28 >>> 37 | w29 << 27) & 0x7FFFFFFFL;
        values[60 + valuesStart] = w29 >>> 4 & 0x7FFFFFFFL;
        values[61 + valuesStart] = (w29 >>> 35 | w30 << 29) & 0x7FFFFFFFL;
        values[62 + valuesStart] = w30 >>> 2 & 0x7FFFFFFFL;
        values[63 + valuesStart] = w30 >>> 33;
        return 248 + packedPtr;
    }

    /**
     * Unpacks 64 32-bit values using 256 bytes, touching 32 words.
     */
    private static long unpack32(long[] values, int valuesStart, long packedPtr) {
        // Access 32 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFFFL;
        values[1 + valuesStart] = w0 >>> 32;
        values[2 + valuesStart] = w1 & 0xFFFFFFFFL;
        values[3 + valuesStart] = w1 >>> 32;
        values[4 + valuesStart] = w2 & 0xFFFFFFFFL;
        values[5 + valuesStart] = w2 >>> 32;
        values[6 + valuesStart] = w3 & 0xFFFFFFFFL;
        values[7 + valuesStart] = w3 >>> 32;
        values[8 + valuesStart] = w4 & 0xFFFFFFFFL;
        values[9 + valuesStart] = w4 >>> 32;
        values[10 + valuesStart] = w5 & 0xFFFFFFFFL;
        values[11 + valuesStart] = w5 >>> 32;
        values[12 + valuesStart] = w6 & 0xFFFFFFFFL;
        values[13 + valuesStart] = w6 >>> 32;
        values[14 + valuesStart] = w7 & 0xFFFFFFFFL;
        values[15 + valuesStart] = w7 >>> 32;
        values[16 + valuesStart] = w8 & 0xFFFFFFFFL;
        values[17 + valuesStart] = w8 >>> 32;
        values[18 + valuesStart] = w9 & 0xFFFFFFFFL;
        values[19 + valuesStart] = w9 >>> 32;
        values[20 + valuesStart] = w10 & 0xFFFFFFFFL;
        values[21 + valuesStart] = w10 >>> 32;
        values[22 + valuesStart] = w11 & 0xFFFFFFFFL;
        values[23 + valuesStart] = w11 >>> 32;
        values[24 + valuesStart] = w12 & 0xFFFFFFFFL;
        values[25 + valuesStart] = w12 >>> 32;
        values[26 + valuesStart] = w13 & 0xFFFFFFFFL;
        values[27 + valuesStart] = w13 >>> 32;
        values[28 + valuesStart] = w14 & 0xFFFFFFFFL;
        values[29 + valuesStart] = w14 >>> 32;
        values[30 + valuesStart] = w15 & 0xFFFFFFFFL;
        values[31 + valuesStart] = w15 >>> 32;
        values[32 + valuesStart] = w16 & 0xFFFFFFFFL;
        values[33 + valuesStart] = w16 >>> 32;
        values[34 + valuesStart] = w17 & 0xFFFFFFFFL;
        values[35 + valuesStart] = w17 >>> 32;
        values[36 + valuesStart] = w18 & 0xFFFFFFFFL;
        values[37 + valuesStart] = w18 >>> 32;
        values[38 + valuesStart] = w19 & 0xFFFFFFFFL;
        values[39 + valuesStart] = w19 >>> 32;
        values[40 + valuesStart] = w20 & 0xFFFFFFFFL;
        values[41 + valuesStart] = w20 >>> 32;
        values[42 + valuesStart] = w21 & 0xFFFFFFFFL;
        values[43 + valuesStart] = w21 >>> 32;
        values[44 + valuesStart] = w22 & 0xFFFFFFFFL;
        values[45 + valuesStart] = w22 >>> 32;
        values[46 + valuesStart] = w23 & 0xFFFFFFFFL;
        values[47 + valuesStart] = w23 >>> 32;
        values[48 + valuesStart] = w24 & 0xFFFFFFFFL;
        values[49 + valuesStart] = w24 >>> 32;
        values[50 + valuesStart] = w25 & 0xFFFFFFFFL;
        values[51 + valuesStart] = w25 >>> 32;
        values[52 + valuesStart] = w26 & 0xFFFFFFFFL;
        values[53 + valuesStart] = w26 >>> 32;
        values[54 + valuesStart] = w27 & 0xFFFFFFFFL;
        values[55 + valuesStart] = w27 >>> 32;
        values[56 + valuesStart] = w28 & 0xFFFFFFFFL;
        values[57 + valuesStart] = w28 >>> 32;
        values[58 + valuesStart] = w29 & 0xFFFFFFFFL;
        values[59 + valuesStart] = w29 >>> 32;
        values[60 + valuesStart] = w30 & 0xFFFFFFFFL;
        values[61 + valuesStart] = w30 >>> 32;
        values[62 + valuesStart] = w31 & 0xFFFFFFFFL;
        values[63 + valuesStart] = w31 >>> 32;
        return 256 + packedPtr;
    }

    /**
     * Unpacks 64 33-bit values using 264 bytes, touching 33 words.
     */
    private static long unpack33(long[] values, int valuesStart, long packedPtr) {
        // Access 33 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 33 | w1 << 31) & 0x1FFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 2 & 0x1FFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 35 | w2 << 29) & 0x1FFFFFFFFL;
        values[4 + valuesStart] = w2 >>> 4 & 0x1FFFFFFFFL;
        values[5 + valuesStart] = (w2 >>> 37 | w3 << 27) & 0x1FFFFFFFFL;
        values[6 + valuesStart] = w3 >>> 6 & 0x1FFFFFFFFL;
        values[7 + valuesStart] = (w3 >>> 39 | w4 << 25) & 0x1FFFFFFFFL;
        values[8 + valuesStart] = w4 >>> 8 & 0x1FFFFFFFFL;
        values[9 + valuesStart] = (w4 >>> 41 | w5 << 23) & 0x1FFFFFFFFL;
        values[10 + valuesStart] = w5 >>> 10 & 0x1FFFFFFFFL;
        values[11 + valuesStart] = (w5 >>> 43 | w6 << 21) & 0x1FFFFFFFFL;
        values[12 + valuesStart] = w6 >>> 12 & 0x1FFFFFFFFL;
        values[13 + valuesStart] = (w6 >>> 45 | w7 << 19) & 0x1FFFFFFFFL;
        values[14 + valuesStart] = w7 >>> 14 & 0x1FFFFFFFFL;
        values[15 + valuesStart] = (w7 >>> 47 | w8 << 17) & 0x1FFFFFFFFL;
        values[16 + valuesStart] = w8 >>> 16 & 0x1FFFFFFFFL;
        values[17 + valuesStart] = (w8 >>> 49 | w9 << 15) & 0x1FFFFFFFFL;
        values[18 + valuesStart] = w9 >>> 18 & 0x1FFFFFFFFL;
        values[19 + valuesStart] = (w9 >>> 51 | w10 << 13) & 0x1FFFFFFFFL;
        values[20 + valuesStart] = w10 >>> 20 & 0x1FFFFFFFFL;
        values[21 + valuesStart] = (w10 >>> 53 | w11 << 11) & 0x1FFFFFFFFL;
        values[22 + valuesStart] = w11 >>> 22 & 0x1FFFFFFFFL;
        values[23 + valuesStart] = (w11 >>> 55 | w12 << 9) & 0x1FFFFFFFFL;
        values[24 + valuesStart] = w12 >>> 24 & 0x1FFFFFFFFL;
        values[25 + valuesStart] = (w12 >>> 57 | w13 << 7) & 0x1FFFFFFFFL;
        values[26 + valuesStart] = w13 >>> 26 & 0x1FFFFFFFFL;
        values[27 + valuesStart] = (w13 >>> 59 | w14 << 5) & 0x1FFFFFFFFL;
        values[28 + valuesStart] = w14 >>> 28 & 0x1FFFFFFFFL;
        values[29 + valuesStart] = (w14 >>> 61 | w15 << 3) & 0x1FFFFFFFFL;
        values[30 + valuesStart] = w15 >>> 30 & 0x1FFFFFFFFL;
        values[31 + valuesStart] = (w15 >>> 63 | w16 << 1) & 0x1FFFFFFFFL;
        values[32 + valuesStart] = (w16 >>> 32 | w17 << 32) & 0x1FFFFFFFFL;
        values[33 + valuesStart] = w17 >>> 1 & 0x1FFFFFFFFL;
        values[34 + valuesStart] = (w17 >>> 34 | w18 << 30) & 0x1FFFFFFFFL;
        values[35 + valuesStart] = w18 >>> 3 & 0x1FFFFFFFFL;
        values[36 + valuesStart] = (w18 >>> 36 | w19 << 28) & 0x1FFFFFFFFL;
        values[37 + valuesStart] = w19 >>> 5 & 0x1FFFFFFFFL;
        values[38 + valuesStart] = (w19 >>> 38 | w20 << 26) & 0x1FFFFFFFFL;
        values[39 + valuesStart] = w20 >>> 7 & 0x1FFFFFFFFL;
        values[40 + valuesStart] = (w20 >>> 40 | w21 << 24) & 0x1FFFFFFFFL;
        values[41 + valuesStart] = w21 >>> 9 & 0x1FFFFFFFFL;
        values[42 + valuesStart] = (w21 >>> 42 | w22 << 22) & 0x1FFFFFFFFL;
        values[43 + valuesStart] = w22 >>> 11 & 0x1FFFFFFFFL;
        values[44 + valuesStart] = (w22 >>> 44 | w23 << 20) & 0x1FFFFFFFFL;
        values[45 + valuesStart] = w23 >>> 13 & 0x1FFFFFFFFL;
        values[46 + valuesStart] = (w23 >>> 46 | w24 << 18) & 0x1FFFFFFFFL;
        values[47 + valuesStart] = w24 >>> 15 & 0x1FFFFFFFFL;
        values[48 + valuesStart] = (w24 >>> 48 | w25 << 16) & 0x1FFFFFFFFL;
        values[49 + valuesStart] = w25 >>> 17 & 0x1FFFFFFFFL;
        values[50 + valuesStart] = (w25 >>> 50 | w26 << 14) & 0x1FFFFFFFFL;
        values[51 + valuesStart] = w26 >>> 19 & 0x1FFFFFFFFL;
        values[52 + valuesStart] = (w26 >>> 52 | w27 << 12) & 0x1FFFFFFFFL;
        values[53 + valuesStart] = w27 >>> 21 & 0x1FFFFFFFFL;
        values[54 + valuesStart] = (w27 >>> 54 | w28 << 10) & 0x1FFFFFFFFL;
        values[55 + valuesStart] = w28 >>> 23 & 0x1FFFFFFFFL;
        values[56 + valuesStart] = (w28 >>> 56 | w29 << 8) & 0x1FFFFFFFFL;
        values[57 + valuesStart] = w29 >>> 25 & 0x1FFFFFFFFL;
        values[58 + valuesStart] = (w29 >>> 58 | w30 << 6) & 0x1FFFFFFFFL;
        values[59 + valuesStart] = w30 >>> 27 & 0x1FFFFFFFFL;
        values[60 + valuesStart] = (w30 >>> 60 | w31 << 4) & 0x1FFFFFFFFL;
        values[61 + valuesStart] = w31 >>> 29 & 0x1FFFFFFFFL;
        values[62 + valuesStart] = (w31 >>> 62 | w32 << 2) & 0x1FFFFFFFFL;
        values[63 + valuesStart] = w32 >>> 31;
        return 264 + packedPtr;
    }

    /**
     * Unpacks 64 34-bit values using 272 bytes, touching 34 words.
     */
    private static long unpack34(long[] values, int valuesStart, long packedPtr) {
        // Access 34 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 34 | w1 << 30) & 0x3FFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 4 & 0x3FFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 38 | w2 << 26) & 0x3FFFFFFFFL;
        values[4 + valuesStart] = w2 >>> 8 & 0x3FFFFFFFFL;
        values[5 + valuesStart] = (w2 >>> 42 | w3 << 22) & 0x3FFFFFFFFL;
        values[6 + valuesStart] = w3 >>> 12 & 0x3FFFFFFFFL;
        values[7 + valuesStart] = (w3 >>> 46 | w4 << 18) & 0x3FFFFFFFFL;
        values[8 + valuesStart] = w4 >>> 16 & 0x3FFFFFFFFL;
        values[9 + valuesStart] = (w4 >>> 50 | w5 << 14) & 0x3FFFFFFFFL;
        values[10 + valuesStart] = w5 >>> 20 & 0x3FFFFFFFFL;
        values[11 + valuesStart] = (w5 >>> 54 | w6 << 10) & 0x3FFFFFFFFL;
        values[12 + valuesStart] = w6 >>> 24 & 0x3FFFFFFFFL;
        values[13 + valuesStart] = (w6 >>> 58 | w7 << 6) & 0x3FFFFFFFFL;
        values[14 + valuesStart] = w7 >>> 28 & 0x3FFFFFFFFL;
        values[15 + valuesStart] = (w7 >>> 62 | w8 << 2) & 0x3FFFFFFFFL;
        values[16 + valuesStart] = (w8 >>> 32 | w9 << 32) & 0x3FFFFFFFFL;
        values[17 + valuesStart] = w9 >>> 2 & 0x3FFFFFFFFL;
        values[18 + valuesStart] = (w9 >>> 36 | w10 << 28) & 0x3FFFFFFFFL;
        values[19 + valuesStart] = w10 >>> 6 & 0x3FFFFFFFFL;
        values[20 + valuesStart] = (w10 >>> 40 | w11 << 24) & 0x3FFFFFFFFL;
        values[21 + valuesStart] = w11 >>> 10 & 0x3FFFFFFFFL;
        values[22 + valuesStart] = (w11 >>> 44 | w12 << 20) & 0x3FFFFFFFFL;
        values[23 + valuesStart] = w12 >>> 14 & 0x3FFFFFFFFL;
        values[24 + valuesStart] = (w12 >>> 48 | w13 << 16) & 0x3FFFFFFFFL;
        values[25 + valuesStart] = w13 >>> 18 & 0x3FFFFFFFFL;
        values[26 + valuesStart] = (w13 >>> 52 | w14 << 12) & 0x3FFFFFFFFL;
        values[27 + valuesStart] = w14 >>> 22 & 0x3FFFFFFFFL;
        values[28 + valuesStart] = (w14 >>> 56 | w15 << 8) & 0x3FFFFFFFFL;
        values[29 + valuesStart] = w15 >>> 26 & 0x3FFFFFFFFL;
        values[30 + valuesStart] = (w15 >>> 60 | w16 << 4) & 0x3FFFFFFFFL;
        values[31 + valuesStart] = w16 >>> 30;
        values[32 + valuesStart] = w17 & 0x3FFFFFFFFL;
        values[33 + valuesStart] = (w17 >>> 34 | w18 << 30) & 0x3FFFFFFFFL;
        values[34 + valuesStart] = w18 >>> 4 & 0x3FFFFFFFFL;
        values[35 + valuesStart] = (w18 >>> 38 | w19 << 26) & 0x3FFFFFFFFL;
        values[36 + valuesStart] = w19 >>> 8 & 0x3FFFFFFFFL;
        values[37 + valuesStart] = (w19 >>> 42 | w20 << 22) & 0x3FFFFFFFFL;
        values[38 + valuesStart] = w20 >>> 12 & 0x3FFFFFFFFL;
        values[39 + valuesStart] = (w20 >>> 46 | w21 << 18) & 0x3FFFFFFFFL;
        values[40 + valuesStart] = w21 >>> 16 & 0x3FFFFFFFFL;
        values[41 + valuesStart] = (w21 >>> 50 | w22 << 14) & 0x3FFFFFFFFL;
        values[42 + valuesStart] = w22 >>> 20 & 0x3FFFFFFFFL;
        values[43 + valuesStart] = (w22 >>> 54 | w23 << 10) & 0x3FFFFFFFFL;
        values[44 + valuesStart] = w23 >>> 24 & 0x3FFFFFFFFL;
        values[45 + valuesStart] = (w23 >>> 58 | w24 << 6) & 0x3FFFFFFFFL;
        values[46 + valuesStart] = w24 >>> 28 & 0x3FFFFFFFFL;
        values[47 + valuesStart] = (w24 >>> 62 | w25 << 2) & 0x3FFFFFFFFL;
        values[48 + valuesStart] = (w25 >>> 32 | w26 << 32) & 0x3FFFFFFFFL;
        values[49 + valuesStart] = w26 >>> 2 & 0x3FFFFFFFFL;
        values[50 + valuesStart] = (w26 >>> 36 | w27 << 28) & 0x3FFFFFFFFL;
        values[51 + valuesStart] = w27 >>> 6 & 0x3FFFFFFFFL;
        values[52 + valuesStart] = (w27 >>> 40 | w28 << 24) & 0x3FFFFFFFFL;
        values[53 + valuesStart] = w28 >>> 10 & 0x3FFFFFFFFL;
        values[54 + valuesStart] = (w28 >>> 44 | w29 << 20) & 0x3FFFFFFFFL;
        values[55 + valuesStart] = w29 >>> 14 & 0x3FFFFFFFFL;
        values[56 + valuesStart] = (w29 >>> 48 | w30 << 16) & 0x3FFFFFFFFL;
        values[57 + valuesStart] = w30 >>> 18 & 0x3FFFFFFFFL;
        values[58 + valuesStart] = (w30 >>> 52 | w31 << 12) & 0x3FFFFFFFFL;
        values[59 + valuesStart] = w31 >>> 22 & 0x3FFFFFFFFL;
        values[60 + valuesStart] = (w31 >>> 56 | w32 << 8) & 0x3FFFFFFFFL;
        values[61 + valuesStart] = w32 >>> 26 & 0x3FFFFFFFFL;
        values[62 + valuesStart] = (w32 >>> 60 | w33 << 4) & 0x3FFFFFFFFL;
        values[63 + valuesStart] = w33 >>> 30;
        return 272 + packedPtr;
    }

    /**
     * Unpacks 64 35-bit values using 280 bytes, touching 35 words.
     */
    private static long unpack35(long[] values, int valuesStart, long packedPtr) {
        // Access 35 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 35 | w1 << 29) & 0x7FFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 6 & 0x7FFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 41 | w2 << 23) & 0x7FFFFFFFFL;
        values[4 + valuesStart] = w2 >>> 12 & 0x7FFFFFFFFL;
        values[5 + valuesStart] = (w2 >>> 47 | w3 << 17) & 0x7FFFFFFFFL;
        values[6 + valuesStart] = w3 >>> 18 & 0x7FFFFFFFFL;
        values[7 + valuesStart] = (w3 >>> 53 | w4 << 11) & 0x7FFFFFFFFL;
        values[8 + valuesStart] = w4 >>> 24 & 0x7FFFFFFFFL;
        values[9 + valuesStart] = (w4 >>> 59 | w5 << 5) & 0x7FFFFFFFFL;
        values[10 + valuesStart] = (w5 >>> 30 | w6 << 34) & 0x7FFFFFFFFL;
        values[11 + valuesStart] = w6 >>> 1 & 0x7FFFFFFFFL;
        values[12 + valuesStart] = (w6 >>> 36 | w7 << 28) & 0x7FFFFFFFFL;
        values[13 + valuesStart] = w7 >>> 7 & 0x7FFFFFFFFL;
        values[14 + valuesStart] = (w7 >>> 42 | w8 << 22) & 0x7FFFFFFFFL;
        values[15 + valuesStart] = w8 >>> 13 & 0x7FFFFFFFFL;
        values[16 + valuesStart] = (w8 >>> 48 | w9 << 16) & 0x7FFFFFFFFL;
        values[17 + valuesStart] = w9 >>> 19 & 0x7FFFFFFFFL;
        values[18 + valuesStart] = (w9 >>> 54 | w10 << 10) & 0x7FFFFFFFFL;
        values[19 + valuesStart] = w10 >>> 25 & 0x7FFFFFFFFL;
        values[20 + valuesStart] = (w10 >>> 60 | w11 << 4) & 0x7FFFFFFFFL;
        values[21 + valuesStart] = (w11 >>> 31 | w12 << 33) & 0x7FFFFFFFFL;
        values[22 + valuesStart] = w12 >>> 2 & 0x7FFFFFFFFL;
        values[23 + valuesStart] = (w12 >>> 37 | w13 << 27) & 0x7FFFFFFFFL;
        values[24 + valuesStart] = w13 >>> 8 & 0x7FFFFFFFFL;
        values[25 + valuesStart] = (w13 >>> 43 | w14 << 21) & 0x7FFFFFFFFL;
        values[26 + valuesStart] = w14 >>> 14 & 0x7FFFFFFFFL;
        values[27 + valuesStart] = (w14 >>> 49 | w15 << 15) & 0x7FFFFFFFFL;
        values[28 + valuesStart] = w15 >>> 20 & 0x7FFFFFFFFL;
        values[29 + valuesStart] = (w15 >>> 55 | w16 << 9) & 0x7FFFFFFFFL;
        values[30 + valuesStart] = w16 >>> 26 & 0x7FFFFFFFFL;
        values[31 + valuesStart] = (w16 >>> 61 | w17 << 3) & 0x7FFFFFFFFL;
        values[32 + valuesStart] = (w17 >>> 32 | w18 << 32) & 0x7FFFFFFFFL;
        values[33 + valuesStart] = w18 >>> 3 & 0x7FFFFFFFFL;
        values[34 + valuesStart] = (w18 >>> 38 | w19 << 26) & 0x7FFFFFFFFL;
        values[35 + valuesStart] = w19 >>> 9 & 0x7FFFFFFFFL;
        values[36 + valuesStart] = (w19 >>> 44 | w20 << 20) & 0x7FFFFFFFFL;
        values[37 + valuesStart] = w20 >>> 15 & 0x7FFFFFFFFL;
        values[38 + valuesStart] = (w20 >>> 50 | w21 << 14) & 0x7FFFFFFFFL;
        values[39 + valuesStart] = w21 >>> 21 & 0x7FFFFFFFFL;
        values[40 + valuesStart] = (w21 >>> 56 | w22 << 8) & 0x7FFFFFFFFL;
        values[41 + valuesStart] = w22 >>> 27 & 0x7FFFFFFFFL;
        values[42 + valuesStart] = (w22 >>> 62 | w23 << 2) & 0x7FFFFFFFFL;
        values[43 + valuesStart] = (w23 >>> 33 | w24 << 31) & 0x7FFFFFFFFL;
        values[44 + valuesStart] = w24 >>> 4 & 0x7FFFFFFFFL;
        values[45 + valuesStart] = (w24 >>> 39 | w25 << 25) & 0x7FFFFFFFFL;
        values[46 + valuesStart] = w25 >>> 10 & 0x7FFFFFFFFL;
        values[47 + valuesStart] = (w25 >>> 45 | w26 << 19) & 0x7FFFFFFFFL;
        values[48 + valuesStart] = w26 >>> 16 & 0x7FFFFFFFFL;
        values[49 + valuesStart] = (w26 >>> 51 | w27 << 13) & 0x7FFFFFFFFL;
        values[50 + valuesStart] = w27 >>> 22 & 0x7FFFFFFFFL;
        values[51 + valuesStart] = (w27 >>> 57 | w28 << 7) & 0x7FFFFFFFFL;
        values[52 + valuesStart] = w28 >>> 28 & 0x7FFFFFFFFL;
        values[53 + valuesStart] = (w28 >>> 63 | w29 << 1) & 0x7FFFFFFFFL;
        values[54 + valuesStart] = (w29 >>> 34 | w30 << 30) & 0x7FFFFFFFFL;
        values[55 + valuesStart] = w30 >>> 5 & 0x7FFFFFFFFL;
        values[56 + valuesStart] = (w30 >>> 40 | w31 << 24) & 0x7FFFFFFFFL;
        values[57 + valuesStart] = w31 >>> 11 & 0x7FFFFFFFFL;
        values[58 + valuesStart] = (w31 >>> 46 | w32 << 18) & 0x7FFFFFFFFL;
        values[59 + valuesStart] = w32 >>> 17 & 0x7FFFFFFFFL;
        values[60 + valuesStart] = (w32 >>> 52 | w33 << 12) & 0x7FFFFFFFFL;
        values[61 + valuesStart] = w33 >>> 23 & 0x7FFFFFFFFL;
        values[62 + valuesStart] = (w33 >>> 58 | w34 << 6) & 0x7FFFFFFFFL;
        values[63 + valuesStart] = w34 >>> 29;
        return 280 + packedPtr;
    }

    /**
     * Unpacks 64 36-bit values using 288 bytes, touching 36 words.
     */
    private static long unpack36(long[] values, int valuesStart, long packedPtr) {
        // Access 36 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 36 | w1 << 28) & 0xFFFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 8 & 0xFFFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 44 | w2 << 20) & 0xFFFFFFFFFL;
        values[4 + valuesStart] = w2 >>> 16 & 0xFFFFFFFFFL;
        values[5 + valuesStart] = (w2 >>> 52 | w3 << 12) & 0xFFFFFFFFFL;
        values[6 + valuesStart] = w3 >>> 24 & 0xFFFFFFFFFL;
        values[7 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0xFFFFFFFFFL;
        values[8 + valuesStart] = (w4 >>> 32 | w5 << 32) & 0xFFFFFFFFFL;
        values[9 + valuesStart] = w5 >>> 4 & 0xFFFFFFFFFL;
        values[10 + valuesStart] = (w5 >>> 40 | w6 << 24) & 0xFFFFFFFFFL;
        values[11 + valuesStart] = w6 >>> 12 & 0xFFFFFFFFFL;
        values[12 + valuesStart] = (w6 >>> 48 | w7 << 16) & 0xFFFFFFFFFL;
        values[13 + valuesStart] = w7 >>> 20 & 0xFFFFFFFFFL;
        values[14 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0xFFFFFFFFFL;
        values[15 + valuesStart] = w8 >>> 28;
        values[16 + valuesStart] = w9 & 0xFFFFFFFFFL;
        values[17 + valuesStart] = (w9 >>> 36 | w10 << 28) & 0xFFFFFFFFFL;
        values[18 + valuesStart] = w10 >>> 8 & 0xFFFFFFFFFL;
        values[19 + valuesStart] = (w10 >>> 44 | w11 << 20) & 0xFFFFFFFFFL;
        values[20 + valuesStart] = w11 >>> 16 & 0xFFFFFFFFFL;
        values[21 + valuesStart] = (w11 >>> 52 | w12 << 12) & 0xFFFFFFFFFL;
        values[22 + valuesStart] = w12 >>> 24 & 0xFFFFFFFFFL;
        values[23 + valuesStart] = (w12 >>> 60 | w13 << 4) & 0xFFFFFFFFFL;
        values[24 + valuesStart] = (w13 >>> 32 | w14 << 32) & 0xFFFFFFFFFL;
        values[25 + valuesStart] = w14 >>> 4 & 0xFFFFFFFFFL;
        values[26 + valuesStart] = (w14 >>> 40 | w15 << 24) & 0xFFFFFFFFFL;
        values[27 + valuesStart] = w15 >>> 12 & 0xFFFFFFFFFL;
        values[28 + valuesStart] = (w15 >>> 48 | w16 << 16) & 0xFFFFFFFFFL;
        values[29 + valuesStart] = w16 >>> 20 & 0xFFFFFFFFFL;
        values[30 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0xFFFFFFFFFL;
        values[31 + valuesStart] = w17 >>> 28;
        values[32 + valuesStart] = w18 & 0xFFFFFFFFFL;
        values[33 + valuesStart] = (w18 >>> 36 | w19 << 28) & 0xFFFFFFFFFL;
        values[34 + valuesStart] = w19 >>> 8 & 0xFFFFFFFFFL;
        values[35 + valuesStart] = (w19 >>> 44 | w20 << 20) & 0xFFFFFFFFFL;
        values[36 + valuesStart] = w20 >>> 16 & 0xFFFFFFFFFL;
        values[37 + valuesStart] = (w20 >>> 52 | w21 << 12) & 0xFFFFFFFFFL;
        values[38 + valuesStart] = w21 >>> 24 & 0xFFFFFFFFFL;
        values[39 + valuesStart] = (w21 >>> 60 | w22 << 4) & 0xFFFFFFFFFL;
        values[40 + valuesStart] = (w22 >>> 32 | w23 << 32) & 0xFFFFFFFFFL;
        values[41 + valuesStart] = w23 >>> 4 & 0xFFFFFFFFFL;
        values[42 + valuesStart] = (w23 >>> 40 | w24 << 24) & 0xFFFFFFFFFL;
        values[43 + valuesStart] = w24 >>> 12 & 0xFFFFFFFFFL;
        values[44 + valuesStart] = (w24 >>> 48 | w25 << 16) & 0xFFFFFFFFFL;
        values[45 + valuesStart] = w25 >>> 20 & 0xFFFFFFFFFL;
        values[46 + valuesStart] = (w25 >>> 56 | w26 << 8) & 0xFFFFFFFFFL;
        values[47 + valuesStart] = w26 >>> 28;
        values[48 + valuesStart] = w27 & 0xFFFFFFFFFL;
        values[49 + valuesStart] = (w27 >>> 36 | w28 << 28) & 0xFFFFFFFFFL;
        values[50 + valuesStart] = w28 >>> 8 & 0xFFFFFFFFFL;
        values[51 + valuesStart] = (w28 >>> 44 | w29 << 20) & 0xFFFFFFFFFL;
        values[52 + valuesStart] = w29 >>> 16 & 0xFFFFFFFFFL;
        values[53 + valuesStart] = (w29 >>> 52 | w30 << 12) & 0xFFFFFFFFFL;
        values[54 + valuesStart] = w30 >>> 24 & 0xFFFFFFFFFL;
        values[55 + valuesStart] = (w30 >>> 60 | w31 << 4) & 0xFFFFFFFFFL;
        values[56 + valuesStart] = (w31 >>> 32 | w32 << 32) & 0xFFFFFFFFFL;
        values[57 + valuesStart] = w32 >>> 4 & 0xFFFFFFFFFL;
        values[58 + valuesStart] = (w32 >>> 40 | w33 << 24) & 0xFFFFFFFFFL;
        values[59 + valuesStart] = w33 >>> 12 & 0xFFFFFFFFFL;
        values[60 + valuesStart] = (w33 >>> 48 | w34 << 16) & 0xFFFFFFFFFL;
        values[61 + valuesStart] = w34 >>> 20 & 0xFFFFFFFFFL;
        values[62 + valuesStart] = (w34 >>> 56 | w35 << 8) & 0xFFFFFFFFFL;
        values[63 + valuesStart] = w35 >>> 28;
        return 288 + packedPtr;
    }

    /**
     * Unpacks 64 37-bit values using 296 bytes, touching 37 words.
     */
    private static long unpack37(long[] values, int valuesStart, long packedPtr) {
        // Access 37 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 37 | w1 << 27) & 0x1FFFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 10 & 0x1FFFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 47 | w2 << 17) & 0x1FFFFFFFFFL;
        values[4 + valuesStart] = w2 >>> 20 & 0x1FFFFFFFFFL;
        values[5 + valuesStart] = (w2 >>> 57 | w3 << 7) & 0x1FFFFFFFFFL;
        values[6 + valuesStart] = (w3 >>> 30 | w4 << 34) & 0x1FFFFFFFFFL;
        values[7 + valuesStart] = w4 >>> 3 & 0x1FFFFFFFFFL;
        values[8 + valuesStart] = (w4 >>> 40 | w5 << 24) & 0x1FFFFFFFFFL;
        values[9 + valuesStart] = w5 >>> 13 & 0x1FFFFFFFFFL;
        values[10 + valuesStart] = (w5 >>> 50 | w6 << 14) & 0x1FFFFFFFFFL;
        values[11 + valuesStart] = w6 >>> 23 & 0x1FFFFFFFFFL;
        values[12 + valuesStart] = (w6 >>> 60 | w7 << 4) & 0x1FFFFFFFFFL;
        values[13 + valuesStart] = (w7 >>> 33 | w8 << 31) & 0x1FFFFFFFFFL;
        values[14 + valuesStart] = w8 >>> 6 & 0x1FFFFFFFFFL;
        values[15 + valuesStart] = (w8 >>> 43 | w9 << 21) & 0x1FFFFFFFFFL;
        values[16 + valuesStart] = w9 >>> 16 & 0x1FFFFFFFFFL;
        values[17 + valuesStart] = (w9 >>> 53 | w10 << 11) & 0x1FFFFFFFFFL;
        values[18 + valuesStart] = w10 >>> 26 & 0x1FFFFFFFFFL;
        values[19 + valuesStart] = (w10 >>> 63 | w11 << 1) & 0x1FFFFFFFFFL;
        values[20 + valuesStart] = (w11 >>> 36 | w12 << 28) & 0x1FFFFFFFFFL;
        values[21 + valuesStart] = w12 >>> 9 & 0x1FFFFFFFFFL;
        values[22 + valuesStart] = (w12 >>> 46 | w13 << 18) & 0x1FFFFFFFFFL;
        values[23 + valuesStart] = w13 >>> 19 & 0x1FFFFFFFFFL;
        values[24 + valuesStart] = (w13 >>> 56 | w14 << 8) & 0x1FFFFFFFFFL;
        values[25 + valuesStart] = (w14 >>> 29 | w15 << 35) & 0x1FFFFFFFFFL;
        values[26 + valuesStart] = w15 >>> 2 & 0x1FFFFFFFFFL;
        values[27 + valuesStart] = (w15 >>> 39 | w16 << 25) & 0x1FFFFFFFFFL;
        values[28 + valuesStart] = w16 >>> 12 & 0x1FFFFFFFFFL;
        values[29 + valuesStart] = (w16 >>> 49 | w17 << 15) & 0x1FFFFFFFFFL;
        values[30 + valuesStart] = w17 >>> 22 & 0x1FFFFFFFFFL;
        values[31 + valuesStart] = (w17 >>> 59 | w18 << 5) & 0x1FFFFFFFFFL;
        values[32 + valuesStart] = (w18 >>> 32 | w19 << 32) & 0x1FFFFFFFFFL;
        values[33 + valuesStart] = w19 >>> 5 & 0x1FFFFFFFFFL;
        values[34 + valuesStart] = (w19 >>> 42 | w20 << 22) & 0x1FFFFFFFFFL;
        values[35 + valuesStart] = w20 >>> 15 & 0x1FFFFFFFFFL;
        values[36 + valuesStart] = (w20 >>> 52 | w21 << 12) & 0x1FFFFFFFFFL;
        values[37 + valuesStart] = w21 >>> 25 & 0x1FFFFFFFFFL;
        values[38 + valuesStart] = (w21 >>> 62 | w22 << 2) & 0x1FFFFFFFFFL;
        values[39 + valuesStart] = (w22 >>> 35 | w23 << 29) & 0x1FFFFFFFFFL;
        values[40 + valuesStart] = w23 >>> 8 & 0x1FFFFFFFFFL;
        values[41 + valuesStart] = (w23 >>> 45 | w24 << 19) & 0x1FFFFFFFFFL;
        values[42 + valuesStart] = w24 >>> 18 & 0x1FFFFFFFFFL;
        values[43 + valuesStart] = (w24 >>> 55 | w25 << 9) & 0x1FFFFFFFFFL;
        values[44 + valuesStart] = (w25 >>> 28 | w26 << 36) & 0x1FFFFFFFFFL;
        values[45 + valuesStart] = w26 >>> 1 & 0x1FFFFFFFFFL;
        values[46 + valuesStart] = (w26 >>> 38 | w27 << 26) & 0x1FFFFFFFFFL;
        values[47 + valuesStart] = w27 >>> 11 & 0x1FFFFFFFFFL;
        values[48 + valuesStart] = (w27 >>> 48 | w28 << 16) & 0x1FFFFFFFFFL;
        values[49 + valuesStart] = w28 >>> 21 & 0x1FFFFFFFFFL;
        values[50 + valuesStart] = (w28 >>> 58 | w29 << 6) & 0x1FFFFFFFFFL;
        values[51 + valuesStart] = (w29 >>> 31 | w30 << 33) & 0x1FFFFFFFFFL;
        values[52 + valuesStart] = w30 >>> 4 & 0x1FFFFFFFFFL;
        values[53 + valuesStart] = (w30 >>> 41 | w31 << 23) & 0x1FFFFFFFFFL;
        values[54 + valuesStart] = w31 >>> 14 & 0x1FFFFFFFFFL;
        values[55 + valuesStart] = (w31 >>> 51 | w32 << 13) & 0x1FFFFFFFFFL;
        values[56 + valuesStart] = w32 >>> 24 & 0x1FFFFFFFFFL;
        values[57 + valuesStart] = (w32 >>> 61 | w33 << 3) & 0x1FFFFFFFFFL;
        values[58 + valuesStart] = (w33 >>> 34 | w34 << 30) & 0x1FFFFFFFFFL;
        values[59 + valuesStart] = w34 >>> 7 & 0x1FFFFFFFFFL;
        values[60 + valuesStart] = (w34 >>> 44 | w35 << 20) & 0x1FFFFFFFFFL;
        values[61 + valuesStart] = w35 >>> 17 & 0x1FFFFFFFFFL;
        values[62 + valuesStart] = (w35 >>> 54 | w36 << 10) & 0x1FFFFFFFFFL;
        values[63 + valuesStart] = w36 >>> 27;
        return 296 + packedPtr;
    }

    /**
     * Unpacks 64 38-bit values using 304 bytes, touching 38 words.
     */
    private static long unpack38(long[] values, int valuesStart, long packedPtr) {
        // Access 38 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 38 | w1 << 26) & 0x3FFFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 12 & 0x3FFFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 50 | w2 << 14) & 0x3FFFFFFFFFL;
        values[4 + valuesStart] = w2 >>> 24 & 0x3FFFFFFFFFL;
        values[5 + valuesStart] = (w2 >>> 62 | w3 << 2) & 0x3FFFFFFFFFL;
        values[6 + valuesStart] = (w3 >>> 36 | w4 << 28) & 0x3FFFFFFFFFL;
        values[7 + valuesStart] = w4 >>> 10 & 0x3FFFFFFFFFL;
        values[8 + valuesStart] = (w4 >>> 48 | w5 << 16) & 0x3FFFFFFFFFL;
        values[9 + valuesStart] = w5 >>> 22 & 0x3FFFFFFFFFL;
        values[10 + valuesStart] = (w5 >>> 60 | w6 << 4) & 0x3FFFFFFFFFL;
        values[11 + valuesStart] = (w6 >>> 34 | w7 << 30) & 0x3FFFFFFFFFL;
        values[12 + valuesStart] = w7 >>> 8 & 0x3FFFFFFFFFL;
        values[13 + valuesStart] = (w7 >>> 46 | w8 << 18) & 0x3FFFFFFFFFL;
        values[14 + valuesStart] = w8 >>> 20 & 0x3FFFFFFFFFL;
        values[15 + valuesStart] = (w8 >>> 58 | w9 << 6) & 0x3FFFFFFFFFL;
        values[16 + valuesStart] = (w9 >>> 32 | w10 << 32) & 0x3FFFFFFFFFL;
        values[17 + valuesStart] = w10 >>> 6 & 0x3FFFFFFFFFL;
        values[18 + valuesStart] = (w10 >>> 44 | w11 << 20) & 0x3FFFFFFFFFL;
        values[19 + valuesStart] = w11 >>> 18 & 0x3FFFFFFFFFL;
        values[20 + valuesStart] = (w11 >>> 56 | w12 << 8) & 0x3FFFFFFFFFL;
        values[21 + valuesStart] = (w12 >>> 30 | w13 << 34) & 0x3FFFFFFFFFL;
        values[22 + valuesStart] = w13 >>> 4 & 0x3FFFFFFFFFL;
        values[23 + valuesStart] = (w13 >>> 42 | w14 << 22) & 0x3FFFFFFFFFL;
        values[24 + valuesStart] = w14 >>> 16 & 0x3FFFFFFFFFL;
        values[25 + valuesStart] = (w14 >>> 54 | w15 << 10) & 0x3FFFFFFFFFL;
        values[26 + valuesStart] = (w15 >>> 28 | w16 << 36) & 0x3FFFFFFFFFL;
        values[27 + valuesStart] = w16 >>> 2 & 0x3FFFFFFFFFL;
        values[28 + valuesStart] = (w16 >>> 40 | w17 << 24) & 0x3FFFFFFFFFL;
        values[29 + valuesStart] = w17 >>> 14 & 0x3FFFFFFFFFL;
        values[30 + valuesStart] = (w17 >>> 52 | w18 << 12) & 0x3FFFFFFFFFL;
        values[31 + valuesStart] = w18 >>> 26;
        values[32 + valuesStart] = w19 & 0x3FFFFFFFFFL;
        values[33 + valuesStart] = (w19 >>> 38 | w20 << 26) & 0x3FFFFFFFFFL;
        values[34 + valuesStart] = w20 >>> 12 & 0x3FFFFFFFFFL;
        values[35 + valuesStart] = (w20 >>> 50 | w21 << 14) & 0x3FFFFFFFFFL;
        values[36 + valuesStart] = w21 >>> 24 & 0x3FFFFFFFFFL;
        values[37 + valuesStart] = (w21 >>> 62 | w22 << 2) & 0x3FFFFFFFFFL;
        values[38 + valuesStart] = (w22 >>> 36 | w23 << 28) & 0x3FFFFFFFFFL;
        values[39 + valuesStart] = w23 >>> 10 & 0x3FFFFFFFFFL;
        values[40 + valuesStart] = (w23 >>> 48 | w24 << 16) & 0x3FFFFFFFFFL;
        values[41 + valuesStart] = w24 >>> 22 & 0x3FFFFFFFFFL;
        values[42 + valuesStart] = (w24 >>> 60 | w25 << 4) & 0x3FFFFFFFFFL;
        values[43 + valuesStart] = (w25 >>> 34 | w26 << 30) & 0x3FFFFFFFFFL;
        values[44 + valuesStart] = w26 >>> 8 & 0x3FFFFFFFFFL;
        values[45 + valuesStart] = (w26 >>> 46 | w27 << 18) & 0x3FFFFFFFFFL;
        values[46 + valuesStart] = w27 >>> 20 & 0x3FFFFFFFFFL;
        values[47 + valuesStart] = (w27 >>> 58 | w28 << 6) & 0x3FFFFFFFFFL;
        values[48 + valuesStart] = (w28 >>> 32 | w29 << 32) & 0x3FFFFFFFFFL;
        values[49 + valuesStart] = w29 >>> 6 & 0x3FFFFFFFFFL;
        values[50 + valuesStart] = (w29 >>> 44 | w30 << 20) & 0x3FFFFFFFFFL;
        values[51 + valuesStart] = w30 >>> 18 & 0x3FFFFFFFFFL;
        values[52 + valuesStart] = (w30 >>> 56 | w31 << 8) & 0x3FFFFFFFFFL;
        values[53 + valuesStart] = (w31 >>> 30 | w32 << 34) & 0x3FFFFFFFFFL;
        values[54 + valuesStart] = w32 >>> 4 & 0x3FFFFFFFFFL;
        values[55 + valuesStart] = (w32 >>> 42 | w33 << 22) & 0x3FFFFFFFFFL;
        values[56 + valuesStart] = w33 >>> 16 & 0x3FFFFFFFFFL;
        values[57 + valuesStart] = (w33 >>> 54 | w34 << 10) & 0x3FFFFFFFFFL;
        values[58 + valuesStart] = (w34 >>> 28 | w35 << 36) & 0x3FFFFFFFFFL;
        values[59 + valuesStart] = w35 >>> 2 & 0x3FFFFFFFFFL;
        values[60 + valuesStart] = (w35 >>> 40 | w36 << 24) & 0x3FFFFFFFFFL;
        values[61 + valuesStart] = w36 >>> 14 & 0x3FFFFFFFFFL;
        values[62 + valuesStart] = (w36 >>> 52 | w37 << 12) & 0x3FFFFFFFFFL;
        values[63 + valuesStart] = w37 >>> 26;
        return 304 + packedPtr;
    }

    /**
     * Unpacks 64 39-bit values using 312 bytes, touching 39 words.
     */
    private static long unpack39(long[] values, int valuesStart, long packedPtr) {
        // Access 39 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 39 | w1 << 25) & 0x7FFFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 14 & 0x7FFFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 53 | w2 << 11) & 0x7FFFFFFFFFL;
        values[4 + valuesStart] = (w2 >>> 28 | w3 << 36) & 0x7FFFFFFFFFL;
        values[5 + valuesStart] = w3 >>> 3 & 0x7FFFFFFFFFL;
        values[6 + valuesStart] = (w3 >>> 42 | w4 << 22) & 0x7FFFFFFFFFL;
        values[7 + valuesStart] = w4 >>> 17 & 0x7FFFFFFFFFL;
        values[8 + valuesStart] = (w4 >>> 56 | w5 << 8) & 0x7FFFFFFFFFL;
        values[9 + valuesStart] = (w5 >>> 31 | w6 << 33) & 0x7FFFFFFFFFL;
        values[10 + valuesStart] = w6 >>> 6 & 0x7FFFFFFFFFL;
        values[11 + valuesStart] = (w6 >>> 45 | w7 << 19) & 0x7FFFFFFFFFL;
        values[12 + valuesStart] = w7 >>> 20 & 0x7FFFFFFFFFL;
        values[13 + valuesStart] = (w7 >>> 59 | w8 << 5) & 0x7FFFFFFFFFL;
        values[14 + valuesStart] = (w8 >>> 34 | w9 << 30) & 0x7FFFFFFFFFL;
        values[15 + valuesStart] = w9 >>> 9 & 0x7FFFFFFFFFL;
        values[16 + valuesStart] = (w9 >>> 48 | w10 << 16) & 0x7FFFFFFFFFL;
        values[17 + valuesStart] = w10 >>> 23 & 0x7FFFFFFFFFL;
        values[18 + valuesStart] = (w10 >>> 62 | w11 << 2) & 0x7FFFFFFFFFL;
        values[19 + valuesStart] = (w11 >>> 37 | w12 << 27) & 0x7FFFFFFFFFL;
        values[20 + valuesStart] = w12 >>> 12 & 0x7FFFFFFFFFL;
        values[21 + valuesStart] = (w12 >>> 51 | w13 << 13) & 0x7FFFFFFFFFL;
        values[22 + valuesStart] = (w13 >>> 26 | w14 << 38) & 0x7FFFFFFFFFL;
        values[23 + valuesStart] = w14 >>> 1 & 0x7FFFFFFFFFL;
        values[24 + valuesStart] = (w14 >>> 40 | w15 << 24) & 0x7FFFFFFFFFL;
        values[25 + valuesStart] = w15 >>> 15 & 0x7FFFFFFFFFL;
        values[26 + valuesStart] = (w15 >>> 54 | w16 << 10) & 0x7FFFFFFFFFL;
        values[27 + valuesStart] = (w16 >>> 29 | w17 << 35) & 0x7FFFFFFFFFL;
        values[28 + valuesStart] = w17 >>> 4 & 0x7FFFFFFFFFL;
        values[29 + valuesStart] = (w17 >>> 43 | w18 << 21) & 0x7FFFFFFFFFL;
        values[30 + valuesStart] = w18 >>> 18 & 0x7FFFFFFFFFL;
        values[31 + valuesStart] = (w18 >>> 57 | w19 << 7) & 0x7FFFFFFFFFL;
        values[32 + valuesStart] = (w19 >>> 32 | w20 << 32) & 0x7FFFFFFFFFL;
        values[33 + valuesStart] = w20 >>> 7 & 0x7FFFFFFFFFL;
        values[34 + valuesStart] = (w20 >>> 46 | w21 << 18) & 0x7FFFFFFFFFL;
        values[35 + valuesStart] = w21 >>> 21 & 0x7FFFFFFFFFL;
        values[36 + valuesStart] = (w21 >>> 60 | w22 << 4) & 0x7FFFFFFFFFL;
        values[37 + valuesStart] = (w22 >>> 35 | w23 << 29) & 0x7FFFFFFFFFL;
        values[38 + valuesStart] = w23 >>> 10 & 0x7FFFFFFFFFL;
        values[39 + valuesStart] = (w23 >>> 49 | w24 << 15) & 0x7FFFFFFFFFL;
        values[40 + valuesStart] = w24 >>> 24 & 0x7FFFFFFFFFL;
        values[41 + valuesStart] = (w24 >>> 63 | w25 << 1) & 0x7FFFFFFFFFL;
        values[42 + valuesStart] = (w25 >>> 38 | w26 << 26) & 0x7FFFFFFFFFL;
        values[43 + valuesStart] = w26 >>> 13 & 0x7FFFFFFFFFL;
        values[44 + valuesStart] = (w26 >>> 52 | w27 << 12) & 0x7FFFFFFFFFL;
        values[45 + valuesStart] = (w27 >>> 27 | w28 << 37) & 0x7FFFFFFFFFL;
        values[46 + valuesStart] = w28 >>> 2 & 0x7FFFFFFFFFL;
        values[47 + valuesStart] = (w28 >>> 41 | w29 << 23) & 0x7FFFFFFFFFL;
        values[48 + valuesStart] = w29 >>> 16 & 0x7FFFFFFFFFL;
        values[49 + valuesStart] = (w29 >>> 55 | w30 << 9) & 0x7FFFFFFFFFL;
        values[50 + valuesStart] = (w30 >>> 30 | w31 << 34) & 0x7FFFFFFFFFL;
        values[51 + valuesStart] = w31 >>> 5 & 0x7FFFFFFFFFL;
        values[52 + valuesStart] = (w31 >>> 44 | w32 << 20) & 0x7FFFFFFFFFL;
        values[53 + valuesStart] = w32 >>> 19 & 0x7FFFFFFFFFL;
        values[54 + valuesStart] = (w32 >>> 58 | w33 << 6) & 0x7FFFFFFFFFL;
        values[55 + valuesStart] = (w33 >>> 33 | w34 << 31) & 0x7FFFFFFFFFL;
        values[56 + valuesStart] = w34 >>> 8 & 0x7FFFFFFFFFL;
        values[57 + valuesStart] = (w34 >>> 47 | w35 << 17) & 0x7FFFFFFFFFL;
        values[58 + valuesStart] = w35 >>> 22 & 0x7FFFFFFFFFL;
        values[59 + valuesStart] = (w35 >>> 61 | w36 << 3) & 0x7FFFFFFFFFL;
        values[60 + valuesStart] = (w36 >>> 36 | w37 << 28) & 0x7FFFFFFFFFL;
        values[61 + valuesStart] = w37 >>> 11 & 0x7FFFFFFFFFL;
        values[62 + valuesStart] = (w37 >>> 50 | w38 << 14) & 0x7FFFFFFFFFL;
        values[63 + valuesStart] = w38 >>> 25;
        return 312 + packedPtr;
    }

    /**
     * Unpacks 64 40-bit values using 320 bytes, touching 40 words.
     */
    private static long unpack40(long[] values, int valuesStart, long packedPtr) {
        // Access 40 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 40 | w1 << 24) & 0xFFFFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 16 & 0xFFFFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 56 | w2 << 8) & 0xFFFFFFFFFFL;
        values[4 + valuesStart] = (w2 >>> 32 | w3 << 32) & 0xFFFFFFFFFFL;
        values[5 + valuesStart] = w3 >>> 8 & 0xFFFFFFFFFFL;
        values[6 + valuesStart] = (w3 >>> 48 | w4 << 16) & 0xFFFFFFFFFFL;
        values[7 + valuesStart] = w4 >>> 24;
        values[8 + valuesStart] = w5 & 0xFFFFFFFFFFL;
        values[9 + valuesStart] = (w5 >>> 40 | w6 << 24) & 0xFFFFFFFFFFL;
        values[10 + valuesStart] = w6 >>> 16 & 0xFFFFFFFFFFL;
        values[11 + valuesStart] = (w6 >>> 56 | w7 << 8) & 0xFFFFFFFFFFL;
        values[12 + valuesStart] = (w7 >>> 32 | w8 << 32) & 0xFFFFFFFFFFL;
        values[13 + valuesStart] = w8 >>> 8 & 0xFFFFFFFFFFL;
        values[14 + valuesStart] = (w8 >>> 48 | w9 << 16) & 0xFFFFFFFFFFL;
        values[15 + valuesStart] = w9 >>> 24;
        values[16 + valuesStart] = w10 & 0xFFFFFFFFFFL;
        values[17 + valuesStart] = (w10 >>> 40 | w11 << 24) & 0xFFFFFFFFFFL;
        values[18 + valuesStart] = w11 >>> 16 & 0xFFFFFFFFFFL;
        values[19 + valuesStart] = (w11 >>> 56 | w12 << 8) & 0xFFFFFFFFFFL;
        values[20 + valuesStart] = (w12 >>> 32 | w13 << 32) & 0xFFFFFFFFFFL;
        values[21 + valuesStart] = w13 >>> 8 & 0xFFFFFFFFFFL;
        values[22 + valuesStart] = (w13 >>> 48 | w14 << 16) & 0xFFFFFFFFFFL;
        values[23 + valuesStart] = w14 >>> 24;
        values[24 + valuesStart] = w15 & 0xFFFFFFFFFFL;
        values[25 + valuesStart] = (w15 >>> 40 | w16 << 24) & 0xFFFFFFFFFFL;
        values[26 + valuesStart] = w16 >>> 16 & 0xFFFFFFFFFFL;
        values[27 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0xFFFFFFFFFFL;
        values[28 + valuesStart] = (w17 >>> 32 | w18 << 32) & 0xFFFFFFFFFFL;
        values[29 + valuesStart] = w18 >>> 8 & 0xFFFFFFFFFFL;
        values[30 + valuesStart] = (w18 >>> 48 | w19 << 16) & 0xFFFFFFFFFFL;
        values[31 + valuesStart] = w19 >>> 24;
        values[32 + valuesStart] = w20 & 0xFFFFFFFFFFL;
        values[33 + valuesStart] = (w20 >>> 40 | w21 << 24) & 0xFFFFFFFFFFL;
        values[34 + valuesStart] = w21 >>> 16 & 0xFFFFFFFFFFL;
        values[35 + valuesStart] = (w21 >>> 56 | w22 << 8) & 0xFFFFFFFFFFL;
        values[36 + valuesStart] = (w22 >>> 32 | w23 << 32) & 0xFFFFFFFFFFL;
        values[37 + valuesStart] = w23 >>> 8 & 0xFFFFFFFFFFL;
        values[38 + valuesStart] = (w23 >>> 48 | w24 << 16) & 0xFFFFFFFFFFL;
        values[39 + valuesStart] = w24 >>> 24;
        values[40 + valuesStart] = w25 & 0xFFFFFFFFFFL;
        values[41 + valuesStart] = (w25 >>> 40 | w26 << 24) & 0xFFFFFFFFFFL;
        values[42 + valuesStart] = w26 >>> 16 & 0xFFFFFFFFFFL;
        values[43 + valuesStart] = (w26 >>> 56 | w27 << 8) & 0xFFFFFFFFFFL;
        values[44 + valuesStart] = (w27 >>> 32 | w28 << 32) & 0xFFFFFFFFFFL;
        values[45 + valuesStart] = w28 >>> 8 & 0xFFFFFFFFFFL;
        values[46 + valuesStart] = (w28 >>> 48 | w29 << 16) & 0xFFFFFFFFFFL;
        values[47 + valuesStart] = w29 >>> 24;
        values[48 + valuesStart] = w30 & 0xFFFFFFFFFFL;
        values[49 + valuesStart] = (w30 >>> 40 | w31 << 24) & 0xFFFFFFFFFFL;
        values[50 + valuesStart] = w31 >>> 16 & 0xFFFFFFFFFFL;
        values[51 + valuesStart] = (w31 >>> 56 | w32 << 8) & 0xFFFFFFFFFFL;
        values[52 + valuesStart] = (w32 >>> 32 | w33 << 32) & 0xFFFFFFFFFFL;
        values[53 + valuesStart] = w33 >>> 8 & 0xFFFFFFFFFFL;
        values[54 + valuesStart] = (w33 >>> 48 | w34 << 16) & 0xFFFFFFFFFFL;
        values[55 + valuesStart] = w34 >>> 24;
        values[56 + valuesStart] = w35 & 0xFFFFFFFFFFL;
        values[57 + valuesStart] = (w35 >>> 40 | w36 << 24) & 0xFFFFFFFFFFL;
        values[58 + valuesStart] = w36 >>> 16 & 0xFFFFFFFFFFL;
        values[59 + valuesStart] = (w36 >>> 56 | w37 << 8) & 0xFFFFFFFFFFL;
        values[60 + valuesStart] = (w37 >>> 32 | w38 << 32) & 0xFFFFFFFFFFL;
        values[61 + valuesStart] = w38 >>> 8 & 0xFFFFFFFFFFL;
        values[62 + valuesStart] = (w38 >>> 48 | w39 << 16) & 0xFFFFFFFFFFL;
        values[63 + valuesStart] = w39 >>> 24;
        return 320 + packedPtr;
    }

    /**
     * Unpacks 64 41-bit values using 328 bytes, touching 41 words.
     */
    private static long unpack41(long[] values, int valuesStart, long packedPtr) {
        // Access 41 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 41 | w1 << 23) & 0x1FFFFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 18 & 0x1FFFFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 59 | w2 << 5) & 0x1FFFFFFFFFFL;
        values[4 + valuesStart] = (w2 >>> 36 | w3 << 28) & 0x1FFFFFFFFFFL;
        values[5 + valuesStart] = w3 >>> 13 & 0x1FFFFFFFFFFL;
        values[6 + valuesStart] = (w3 >>> 54 | w4 << 10) & 0x1FFFFFFFFFFL;
        values[7 + valuesStart] = (w4 >>> 31 | w5 << 33) & 0x1FFFFFFFFFFL;
        values[8 + valuesStart] = w5 >>> 8 & 0x1FFFFFFFFFFL;
        values[9 + valuesStart] = (w5 >>> 49 | w6 << 15) & 0x1FFFFFFFFFFL;
        values[10 + valuesStart] = (w6 >>> 26 | w7 << 38) & 0x1FFFFFFFFFFL;
        values[11 + valuesStart] = w7 >>> 3 & 0x1FFFFFFFFFFL;
        values[12 + valuesStart] = (w7 >>> 44 | w8 << 20) & 0x1FFFFFFFFFFL;
        values[13 + valuesStart] = w8 >>> 21 & 0x1FFFFFFFFFFL;
        values[14 + valuesStart] = (w8 >>> 62 | w9 << 2) & 0x1FFFFFFFFFFL;
        values[15 + valuesStart] = (w9 >>> 39 | w10 << 25) & 0x1FFFFFFFFFFL;
        values[16 + valuesStart] = w10 >>> 16 & 0x1FFFFFFFFFFL;
        values[17 + valuesStart] = (w10 >>> 57 | w11 << 7) & 0x1FFFFFFFFFFL;
        values[18 + valuesStart] = (w11 >>> 34 | w12 << 30) & 0x1FFFFFFFFFFL;
        values[19 + valuesStart] = w12 >>> 11 & 0x1FFFFFFFFFFL;
        values[20 + valuesStart] = (w12 >>> 52 | w13 << 12) & 0x1FFFFFFFFFFL;
        values[21 + valuesStart] = (w13 >>> 29 | w14 << 35) & 0x1FFFFFFFFFFL;
        values[22 + valuesStart] = w14 >>> 6 & 0x1FFFFFFFFFFL;
        values[23 + valuesStart] = (w14 >>> 47 | w15 << 17) & 0x1FFFFFFFFFFL;
        values[24 + valuesStart] = (w15 >>> 24 | w16 << 40) & 0x1FFFFFFFFFFL;
        values[25 + valuesStart] = w16 >>> 1 & 0x1FFFFFFFFFFL;
        values[26 + valuesStart] = (w16 >>> 42 | w17 << 22) & 0x1FFFFFFFFFFL;
        values[27 + valuesStart] = w17 >>> 19 & 0x1FFFFFFFFFFL;
        values[28 + valuesStart] = (w17 >>> 60 | w18 << 4) & 0x1FFFFFFFFFFL;
        values[29 + valuesStart] = (w18 >>> 37 | w19 << 27) & 0x1FFFFFFFFFFL;
        values[30 + valuesStart] = w19 >>> 14 & 0x1FFFFFFFFFFL;
        values[31 + valuesStart] = (w19 >>> 55 | w20 << 9) & 0x1FFFFFFFFFFL;
        values[32 + valuesStart] = (w20 >>> 32 | w21 << 32) & 0x1FFFFFFFFFFL;
        values[33 + valuesStart] = w21 >>> 9 & 0x1FFFFFFFFFFL;
        values[34 + valuesStart] = (w21 >>> 50 | w22 << 14) & 0x1FFFFFFFFFFL;
        values[35 + valuesStart] = (w22 >>> 27 | w23 << 37) & 0x1FFFFFFFFFFL;
        values[36 + valuesStart] = w23 >>> 4 & 0x1FFFFFFFFFFL;
        values[37 + valuesStart] = (w23 >>> 45 | w24 << 19) & 0x1FFFFFFFFFFL;
        values[38 + valuesStart] = w24 >>> 22 & 0x1FFFFFFFFFFL;
        values[39 + valuesStart] = (w24 >>> 63 | w25 << 1) & 0x1FFFFFFFFFFL;
        values[40 + valuesStart] = (w25 >>> 40 | w26 << 24) & 0x1FFFFFFFFFFL;
        values[41 + valuesStart] = w26 >>> 17 & 0x1FFFFFFFFFFL;
        values[42 + valuesStart] = (w26 >>> 58 | w27 << 6) & 0x1FFFFFFFFFFL;
        values[43 + valuesStart] = (w27 >>> 35 | w28 << 29) & 0x1FFFFFFFFFFL;
        values[44 + valuesStart] = w28 >>> 12 & 0x1FFFFFFFFFFL;
        values[45 + valuesStart] = (w28 >>> 53 | w29 << 11) & 0x1FFFFFFFFFFL;
        values[46 + valuesStart] = (w29 >>> 30 | w30 << 34) & 0x1FFFFFFFFFFL;
        values[47 + valuesStart] = w30 >>> 7 & 0x1FFFFFFFFFFL;
        values[48 + valuesStart] = (w30 >>> 48 | w31 << 16) & 0x1FFFFFFFFFFL;
        values[49 + valuesStart] = (w31 >>> 25 | w32 << 39) & 0x1FFFFFFFFFFL;
        values[50 + valuesStart] = w32 >>> 2 & 0x1FFFFFFFFFFL;
        values[51 + valuesStart] = (w32 >>> 43 | w33 << 21) & 0x1FFFFFFFFFFL;
        values[52 + valuesStart] = w33 >>> 20 & 0x1FFFFFFFFFFL;
        values[53 + valuesStart] = (w33 >>> 61 | w34 << 3) & 0x1FFFFFFFFFFL;
        values[54 + valuesStart] = (w34 >>> 38 | w35 << 26) & 0x1FFFFFFFFFFL;
        values[55 + valuesStart] = w35 >>> 15 & 0x1FFFFFFFFFFL;
        values[56 + valuesStart] = (w35 >>> 56 | w36 << 8) & 0x1FFFFFFFFFFL;
        values[57 + valuesStart] = (w36 >>> 33 | w37 << 31) & 0x1FFFFFFFFFFL;
        values[58 + valuesStart] = w37 >>> 10 & 0x1FFFFFFFFFFL;
        values[59 + valuesStart] = (w37 >>> 51 | w38 << 13) & 0x1FFFFFFFFFFL;
        values[60 + valuesStart] = (w38 >>> 28 | w39 << 36) & 0x1FFFFFFFFFFL;
        values[61 + valuesStart] = w39 >>> 5 & 0x1FFFFFFFFFFL;
        values[62 + valuesStart] = (w39 >>> 46 | w40 << 18) & 0x1FFFFFFFFFFL;
        values[63 + valuesStart] = w40 >>> 23;
        return 328 + packedPtr;
    }

    /**
     * Unpacks 64 42-bit values using 336 bytes, touching 42 words.
     */
    private static long unpack42(long[] values, int valuesStart, long packedPtr) {
        // Access 42 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 42 | w1 << 22) & 0x3FFFFFFFFFFL;
        values[2 + valuesStart] = w1 >>> 20 & 0x3FFFFFFFFFFL;
        values[3 + valuesStart] = (w1 >>> 62 | w2 << 2) & 0x3FFFFFFFFFFL;
        values[4 + valuesStart] = (w2 >>> 40 | w3 << 24) & 0x3FFFFFFFFFFL;
        values[5 + valuesStart] = w3 >>> 18 & 0x3FFFFFFFFFFL;
        values[6 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0x3FFFFFFFFFFL;
        values[7 + valuesStart] = (w4 >>> 38 | w5 << 26) & 0x3FFFFFFFFFFL;
        values[8 + valuesStart] = w5 >>> 16 & 0x3FFFFFFFFFFL;
        values[9 + valuesStart] = (w5 >>> 58 | w6 << 6) & 0x3FFFFFFFFFFL;
        values[10 + valuesStart] = (w6 >>> 36 | w7 << 28) & 0x3FFFFFFFFFFL;
        values[11 + valuesStart] = w7 >>> 14 & 0x3FFFFFFFFFFL;
        values[12 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0x3FFFFFFFFFFL;
        values[13 + valuesStart] = (w8 >>> 34 | w9 << 30) & 0x3FFFFFFFFFFL;
        values[14 + valuesStart] = w9 >>> 12 & 0x3FFFFFFFFFFL;
        values[15 + valuesStart] = (w9 >>> 54 | w10 << 10) & 0x3FFFFFFFFFFL;
        values[16 + valuesStart] = (w10 >>> 32 | w11 << 32) & 0x3FFFFFFFFFFL;
        values[17 + valuesStart] = w11 >>> 10 & 0x3FFFFFFFFFFL;
        values[18 + valuesStart] = (w11 >>> 52 | w12 << 12) & 0x3FFFFFFFFFFL;
        values[19 + valuesStart] = (w12 >>> 30 | w13 << 34) & 0x3FFFFFFFFFFL;
        values[20 + valuesStart] = w13 >>> 8 & 0x3FFFFFFFFFFL;
        values[21 + valuesStart] = (w13 >>> 50 | w14 << 14) & 0x3FFFFFFFFFFL;
        values[22 + valuesStart] = (w14 >>> 28 | w15 << 36) & 0x3FFFFFFFFFFL;
        values[23 + valuesStart] = w15 >>> 6 & 0x3FFFFFFFFFFL;
        values[24 + valuesStart] = (w15 >>> 48 | w16 << 16) & 0x3FFFFFFFFFFL;
        values[25 + valuesStart] = (w16 >>> 26 | w17 << 38) & 0x3FFFFFFFFFFL;
        values[26 + valuesStart] = w17 >>> 4 & 0x3FFFFFFFFFFL;
        values[27 + valuesStart] = (w17 >>> 46 | w18 << 18) & 0x3FFFFFFFFFFL;
        values[28 + valuesStart] = (w18 >>> 24 | w19 << 40) & 0x3FFFFFFFFFFL;
        values[29 + valuesStart] = w19 >>> 2 & 0x3FFFFFFFFFFL;
        values[30 + valuesStart] = (w19 >>> 44 | w20 << 20) & 0x3FFFFFFFFFFL;
        values[31 + valuesStart] = w20 >>> 22;
        values[32 + valuesStart] = w21 & 0x3FFFFFFFFFFL;
        values[33 + valuesStart] = (w21 >>> 42 | w22 << 22) & 0x3FFFFFFFFFFL;
        values[34 + valuesStart] = w22 >>> 20 & 0x3FFFFFFFFFFL;
        values[35 + valuesStart] = (w22 >>> 62 | w23 << 2) & 0x3FFFFFFFFFFL;
        values[36 + valuesStart] = (w23 >>> 40 | w24 << 24) & 0x3FFFFFFFFFFL;
        values[37 + valuesStart] = w24 >>> 18 & 0x3FFFFFFFFFFL;
        values[38 + valuesStart] = (w24 >>> 60 | w25 << 4) & 0x3FFFFFFFFFFL;
        values[39 + valuesStart] = (w25 >>> 38 | w26 << 26) & 0x3FFFFFFFFFFL;
        values[40 + valuesStart] = w26 >>> 16 & 0x3FFFFFFFFFFL;
        values[41 + valuesStart] = (w26 >>> 58 | w27 << 6) & 0x3FFFFFFFFFFL;
        values[42 + valuesStart] = (w27 >>> 36 | w28 << 28) & 0x3FFFFFFFFFFL;
        values[43 + valuesStart] = w28 >>> 14 & 0x3FFFFFFFFFFL;
        values[44 + valuesStart] = (w28 >>> 56 | w29 << 8) & 0x3FFFFFFFFFFL;
        values[45 + valuesStart] = (w29 >>> 34 | w30 << 30) & 0x3FFFFFFFFFFL;
        values[46 + valuesStart] = w30 >>> 12 & 0x3FFFFFFFFFFL;
        values[47 + valuesStart] = (w30 >>> 54 | w31 << 10) & 0x3FFFFFFFFFFL;
        values[48 + valuesStart] = (w31 >>> 32 | w32 << 32) & 0x3FFFFFFFFFFL;
        values[49 + valuesStart] = w32 >>> 10 & 0x3FFFFFFFFFFL;
        values[50 + valuesStart] = (w32 >>> 52 | w33 << 12) & 0x3FFFFFFFFFFL;
        values[51 + valuesStart] = (w33 >>> 30 | w34 << 34) & 0x3FFFFFFFFFFL;
        values[52 + valuesStart] = w34 >>> 8 & 0x3FFFFFFFFFFL;
        values[53 + valuesStart] = (w34 >>> 50 | w35 << 14) & 0x3FFFFFFFFFFL;
        values[54 + valuesStart] = (w35 >>> 28 | w36 << 36) & 0x3FFFFFFFFFFL;
        values[55 + valuesStart] = w36 >>> 6 & 0x3FFFFFFFFFFL;
        values[56 + valuesStart] = (w36 >>> 48 | w37 << 16) & 0x3FFFFFFFFFFL;
        values[57 + valuesStart] = (w37 >>> 26 | w38 << 38) & 0x3FFFFFFFFFFL;
        values[58 + valuesStart] = w38 >>> 4 & 0x3FFFFFFFFFFL;
        values[59 + valuesStart] = (w38 >>> 46 | w39 << 18) & 0x3FFFFFFFFFFL;
        values[60 + valuesStart] = (w39 >>> 24 | w40 << 40) & 0x3FFFFFFFFFFL;
        values[61 + valuesStart] = w40 >>> 2 & 0x3FFFFFFFFFFL;
        values[62 + valuesStart] = (w40 >>> 44 | w41 << 20) & 0x3FFFFFFFFFFL;
        values[63 + valuesStart] = w41 >>> 22;
        return 336 + packedPtr;
    }

    /**
     * Unpacks 64 43-bit values using 344 bytes, touching 43 words.
     */
    private static long unpack43(long[] values, int valuesStart, long packedPtr) {
        // Access 43 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 43 | w1 << 21) & 0x7FFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 22 | w2 << 42) & 0x7FFFFFFFFFFL;
        values[3 + valuesStart] = w2 >>> 1 & 0x7FFFFFFFFFFL;
        values[4 + valuesStart] = (w2 >>> 44 | w3 << 20) & 0x7FFFFFFFFFFL;
        values[5 + valuesStart] = (w3 >>> 23 | w4 << 41) & 0x7FFFFFFFFFFL;
        values[6 + valuesStart] = w4 >>> 2 & 0x7FFFFFFFFFFL;
        values[7 + valuesStart] = (w4 >>> 45 | w5 << 19) & 0x7FFFFFFFFFFL;
        values[8 + valuesStart] = (w5 >>> 24 | w6 << 40) & 0x7FFFFFFFFFFL;
        values[9 + valuesStart] = w6 >>> 3 & 0x7FFFFFFFFFFL;
        values[10 + valuesStart] = (w6 >>> 46 | w7 << 18) & 0x7FFFFFFFFFFL;
        values[11 + valuesStart] = (w7 >>> 25 | w8 << 39) & 0x7FFFFFFFFFFL;
        values[12 + valuesStart] = w8 >>> 4 & 0x7FFFFFFFFFFL;
        values[13 + valuesStart] = (w8 >>> 47 | w9 << 17) & 0x7FFFFFFFFFFL;
        values[14 + valuesStart] = (w9 >>> 26 | w10 << 38) & 0x7FFFFFFFFFFL;
        values[15 + valuesStart] = w10 >>> 5 & 0x7FFFFFFFFFFL;
        values[16 + valuesStart] = (w10 >>> 48 | w11 << 16) & 0x7FFFFFFFFFFL;
        values[17 + valuesStart] = (w11 >>> 27 | w12 << 37) & 0x7FFFFFFFFFFL;
        values[18 + valuesStart] = w12 >>> 6 & 0x7FFFFFFFFFFL;
        values[19 + valuesStart] = (w12 >>> 49 | w13 << 15) & 0x7FFFFFFFFFFL;
        values[20 + valuesStart] = (w13 >>> 28 | w14 << 36) & 0x7FFFFFFFFFFL;
        values[21 + valuesStart] = w14 >>> 7 & 0x7FFFFFFFFFFL;
        values[22 + valuesStart] = (w14 >>> 50 | w15 << 14) & 0x7FFFFFFFFFFL;
        values[23 + valuesStart] = (w15 >>> 29 | w16 << 35) & 0x7FFFFFFFFFFL;
        values[24 + valuesStart] = w16 >>> 8 & 0x7FFFFFFFFFFL;
        values[25 + valuesStart] = (w16 >>> 51 | w17 << 13) & 0x7FFFFFFFFFFL;
        values[26 + valuesStart] = (w17 >>> 30 | w18 << 34) & 0x7FFFFFFFFFFL;
        values[27 + valuesStart] = w18 >>> 9 & 0x7FFFFFFFFFFL;
        values[28 + valuesStart] = (w18 >>> 52 | w19 << 12) & 0x7FFFFFFFFFFL;
        values[29 + valuesStart] = (w19 >>> 31 | w20 << 33) & 0x7FFFFFFFFFFL;
        values[30 + valuesStart] = w20 >>> 10 & 0x7FFFFFFFFFFL;
        values[31 + valuesStart] = (w20 >>> 53 | w21 << 11) & 0x7FFFFFFFFFFL;
        values[32 + valuesStart] = (w21 >>> 32 | w22 << 32) & 0x7FFFFFFFFFFL;
        values[33 + valuesStart] = w22 >>> 11 & 0x7FFFFFFFFFFL;
        values[34 + valuesStart] = (w22 >>> 54 | w23 << 10) & 0x7FFFFFFFFFFL;
        values[35 + valuesStart] = (w23 >>> 33 | w24 << 31) & 0x7FFFFFFFFFFL;
        values[36 + valuesStart] = w24 >>> 12 & 0x7FFFFFFFFFFL;
        values[37 + valuesStart] = (w24 >>> 55 | w25 << 9) & 0x7FFFFFFFFFFL;
        values[38 + valuesStart] = (w25 >>> 34 | w26 << 30) & 0x7FFFFFFFFFFL;
        values[39 + valuesStart] = w26 >>> 13 & 0x7FFFFFFFFFFL;
        values[40 + valuesStart] = (w26 >>> 56 | w27 << 8) & 0x7FFFFFFFFFFL;
        values[41 + valuesStart] = (w27 >>> 35 | w28 << 29) & 0x7FFFFFFFFFFL;
        values[42 + valuesStart] = w28 >>> 14 & 0x7FFFFFFFFFFL;
        values[43 + valuesStart] = (w28 >>> 57 | w29 << 7) & 0x7FFFFFFFFFFL;
        values[44 + valuesStart] = (w29 >>> 36 | w30 << 28) & 0x7FFFFFFFFFFL;
        values[45 + valuesStart] = w30 >>> 15 & 0x7FFFFFFFFFFL;
        values[46 + valuesStart] = (w30 >>> 58 | w31 << 6) & 0x7FFFFFFFFFFL;
        values[47 + valuesStart] = (w31 >>> 37 | w32 << 27) & 0x7FFFFFFFFFFL;
        values[48 + valuesStart] = w32 >>> 16 & 0x7FFFFFFFFFFL;
        values[49 + valuesStart] = (w32 >>> 59 | w33 << 5) & 0x7FFFFFFFFFFL;
        values[50 + valuesStart] = (w33 >>> 38 | w34 << 26) & 0x7FFFFFFFFFFL;
        values[51 + valuesStart] = w34 >>> 17 & 0x7FFFFFFFFFFL;
        values[52 + valuesStart] = (w34 >>> 60 | w35 << 4) & 0x7FFFFFFFFFFL;
        values[53 + valuesStart] = (w35 >>> 39 | w36 << 25) & 0x7FFFFFFFFFFL;
        values[54 + valuesStart] = w36 >>> 18 & 0x7FFFFFFFFFFL;
        values[55 + valuesStart] = (w36 >>> 61 | w37 << 3) & 0x7FFFFFFFFFFL;
        values[56 + valuesStart] = (w37 >>> 40 | w38 << 24) & 0x7FFFFFFFFFFL;
        values[57 + valuesStart] = w38 >>> 19 & 0x7FFFFFFFFFFL;
        values[58 + valuesStart] = (w38 >>> 62 | w39 << 2) & 0x7FFFFFFFFFFL;
        values[59 + valuesStart] = (w39 >>> 41 | w40 << 23) & 0x7FFFFFFFFFFL;
        values[60 + valuesStart] = w40 >>> 20 & 0x7FFFFFFFFFFL;
        values[61 + valuesStart] = (w40 >>> 63 | w41 << 1) & 0x7FFFFFFFFFFL;
        values[62 + valuesStart] = (w41 >>> 42 | w42 << 22) & 0x7FFFFFFFFFFL;
        values[63 + valuesStart] = w42 >>> 21;
        return 344 + packedPtr;
    }

    /**
     * Unpacks 64 44-bit values using 352 bytes, touching 44 words.
     */
    private static long unpack44(long[] values, int valuesStart, long packedPtr) {
        // Access 44 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 44 | w1 << 20) & 0xFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 24 | w2 << 40) & 0xFFFFFFFFFFFL;
        values[3 + valuesStart] = w2 >>> 4 & 0xFFFFFFFFFFFL;
        values[4 + valuesStart] = (w2 >>> 48 | w3 << 16) & 0xFFFFFFFFFFFL;
        values[5 + valuesStart] = (w3 >>> 28 | w4 << 36) & 0xFFFFFFFFFFFL;
        values[6 + valuesStart] = w4 >>> 8 & 0xFFFFFFFFFFFL;
        values[7 + valuesStart] = (w4 >>> 52 | w5 << 12) & 0xFFFFFFFFFFFL;
        values[8 + valuesStart] = (w5 >>> 32 | w6 << 32) & 0xFFFFFFFFFFFL;
        values[9 + valuesStart] = w6 >>> 12 & 0xFFFFFFFFFFFL;
        values[10 + valuesStart] = (w6 >>> 56 | w7 << 8) & 0xFFFFFFFFFFFL;
        values[11 + valuesStart] = (w7 >>> 36 | w8 << 28) & 0xFFFFFFFFFFFL;
        values[12 + valuesStart] = w8 >>> 16 & 0xFFFFFFFFFFFL;
        values[13 + valuesStart] = (w8 >>> 60 | w9 << 4) & 0xFFFFFFFFFFFL;
        values[14 + valuesStart] = (w9 >>> 40 | w10 << 24) & 0xFFFFFFFFFFFL;
        values[15 + valuesStart] = w10 >>> 20;
        values[16 + valuesStart] = w11 & 0xFFFFFFFFFFFL;
        values[17 + valuesStart] = (w11 >>> 44 | w12 << 20) & 0xFFFFFFFFFFFL;
        values[18 + valuesStart] = (w12 >>> 24 | w13 << 40) & 0xFFFFFFFFFFFL;
        values[19 + valuesStart] = w13 >>> 4 & 0xFFFFFFFFFFFL;
        values[20 + valuesStart] = (w13 >>> 48 | w14 << 16) & 0xFFFFFFFFFFFL;
        values[21 + valuesStart] = (w14 >>> 28 | w15 << 36) & 0xFFFFFFFFFFFL;
        values[22 + valuesStart] = w15 >>> 8 & 0xFFFFFFFFFFFL;
        values[23 + valuesStart] = (w15 >>> 52 | w16 << 12) & 0xFFFFFFFFFFFL;
        values[24 + valuesStart] = (w16 >>> 32 | w17 << 32) & 0xFFFFFFFFFFFL;
        values[25 + valuesStart] = w17 >>> 12 & 0xFFFFFFFFFFFL;
        values[26 + valuesStart] = (w17 >>> 56 | w18 << 8) & 0xFFFFFFFFFFFL;
        values[27 + valuesStart] = (w18 >>> 36 | w19 << 28) & 0xFFFFFFFFFFFL;
        values[28 + valuesStart] = w19 >>> 16 & 0xFFFFFFFFFFFL;
        values[29 + valuesStart] = (w19 >>> 60 | w20 << 4) & 0xFFFFFFFFFFFL;
        values[30 + valuesStart] = (w20 >>> 40 | w21 << 24) & 0xFFFFFFFFFFFL;
        values[31 + valuesStart] = w21 >>> 20;
        values[32 + valuesStart] = w22 & 0xFFFFFFFFFFFL;
        values[33 + valuesStart] = (w22 >>> 44 | w23 << 20) & 0xFFFFFFFFFFFL;
        values[34 + valuesStart] = (w23 >>> 24 | w24 << 40) & 0xFFFFFFFFFFFL;
        values[35 + valuesStart] = w24 >>> 4 & 0xFFFFFFFFFFFL;
        values[36 + valuesStart] = (w24 >>> 48 | w25 << 16) & 0xFFFFFFFFFFFL;
        values[37 + valuesStart] = (w25 >>> 28 | w26 << 36) & 0xFFFFFFFFFFFL;
        values[38 + valuesStart] = w26 >>> 8 & 0xFFFFFFFFFFFL;
        values[39 + valuesStart] = (w26 >>> 52 | w27 << 12) & 0xFFFFFFFFFFFL;
        values[40 + valuesStart] = (w27 >>> 32 | w28 << 32) & 0xFFFFFFFFFFFL;
        values[41 + valuesStart] = w28 >>> 12 & 0xFFFFFFFFFFFL;
        values[42 + valuesStart] = (w28 >>> 56 | w29 << 8) & 0xFFFFFFFFFFFL;
        values[43 + valuesStart] = (w29 >>> 36 | w30 << 28) & 0xFFFFFFFFFFFL;
        values[44 + valuesStart] = w30 >>> 16 & 0xFFFFFFFFFFFL;
        values[45 + valuesStart] = (w30 >>> 60 | w31 << 4) & 0xFFFFFFFFFFFL;
        values[46 + valuesStart] = (w31 >>> 40 | w32 << 24) & 0xFFFFFFFFFFFL;
        values[47 + valuesStart] = w32 >>> 20;
        values[48 + valuesStart] = w33 & 0xFFFFFFFFFFFL;
        values[49 + valuesStart] = (w33 >>> 44 | w34 << 20) & 0xFFFFFFFFFFFL;
        values[50 + valuesStart] = (w34 >>> 24 | w35 << 40) & 0xFFFFFFFFFFFL;
        values[51 + valuesStart] = w35 >>> 4 & 0xFFFFFFFFFFFL;
        values[52 + valuesStart] = (w35 >>> 48 | w36 << 16) & 0xFFFFFFFFFFFL;
        values[53 + valuesStart] = (w36 >>> 28 | w37 << 36) & 0xFFFFFFFFFFFL;
        values[54 + valuesStart] = w37 >>> 8 & 0xFFFFFFFFFFFL;
        values[55 + valuesStart] = (w37 >>> 52 | w38 << 12) & 0xFFFFFFFFFFFL;
        values[56 + valuesStart] = (w38 >>> 32 | w39 << 32) & 0xFFFFFFFFFFFL;
        values[57 + valuesStart] = w39 >>> 12 & 0xFFFFFFFFFFFL;
        values[58 + valuesStart] = (w39 >>> 56 | w40 << 8) & 0xFFFFFFFFFFFL;
        values[59 + valuesStart] = (w40 >>> 36 | w41 << 28) & 0xFFFFFFFFFFFL;
        values[60 + valuesStart] = w41 >>> 16 & 0xFFFFFFFFFFFL;
        values[61 + valuesStart] = (w41 >>> 60 | w42 << 4) & 0xFFFFFFFFFFFL;
        values[62 + valuesStart] = (w42 >>> 40 | w43 << 24) & 0xFFFFFFFFFFFL;
        values[63 + valuesStart] = w43 >>> 20;
        return 352 + packedPtr;
    }

    /**
     * Unpacks 64 45-bit values using 360 bytes, touching 45 words.
     */
    private static long unpack45(long[] values, int valuesStart, long packedPtr) {
        // Access 45 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 45 | w1 << 19) & 0x1FFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 26 | w2 << 38) & 0x1FFFFFFFFFFFL;
        values[3 + valuesStart] = w2 >>> 7 & 0x1FFFFFFFFFFFL;
        values[4 + valuesStart] = (w2 >>> 52 | w3 << 12) & 0x1FFFFFFFFFFFL;
        values[5 + valuesStart] = (w3 >>> 33 | w4 << 31) & 0x1FFFFFFFFFFFL;
        values[6 + valuesStart] = w4 >>> 14 & 0x1FFFFFFFFFFFL;
        values[7 + valuesStart] = (w4 >>> 59 | w5 << 5) & 0x1FFFFFFFFFFFL;
        values[8 + valuesStart] = (w5 >>> 40 | w6 << 24) & 0x1FFFFFFFFFFFL;
        values[9 + valuesStart] = (w6 >>> 21 | w7 << 43) & 0x1FFFFFFFFFFFL;
        values[10 + valuesStart] = w7 >>> 2 & 0x1FFFFFFFFFFFL;
        values[11 + valuesStart] = (w7 >>> 47 | w8 << 17) & 0x1FFFFFFFFFFFL;
        values[12 + valuesStart] = (w8 >>> 28 | w9 << 36) & 0x1FFFFFFFFFFFL;
        values[13 + valuesStart] = w9 >>> 9 & 0x1FFFFFFFFFFFL;
        values[14 + valuesStart] = (w9 >>> 54 | w10 << 10) & 0x1FFFFFFFFFFFL;
        values[15 + valuesStart] = (w10 >>> 35 | w11 << 29) & 0x1FFFFFFFFFFFL;
        values[16 + valuesStart] = w11 >>> 16 & 0x1FFFFFFFFFFFL;
        values[17 + valuesStart] = (w11 >>> 61 | w12 << 3) & 0x1FFFFFFFFFFFL;
        values[18 + valuesStart] = (w12 >>> 42 | w13 << 22) & 0x1FFFFFFFFFFFL;
        values[19 + valuesStart] = (w13 >>> 23 | w14 << 41) & 0x1FFFFFFFFFFFL;
        values[20 + valuesStart] = w14 >>> 4 & 0x1FFFFFFFFFFFL;
        values[21 + valuesStart] = (w14 >>> 49 | w15 << 15) & 0x1FFFFFFFFFFFL;
        values[22 + valuesStart] = (w15 >>> 30 | w16 << 34) & 0x1FFFFFFFFFFFL;
        values[23 + valuesStart] = w16 >>> 11 & 0x1FFFFFFFFFFFL;
        values[24 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0x1FFFFFFFFFFFL;
        values[25 + valuesStart] = (w17 >>> 37 | w18 << 27) & 0x1FFFFFFFFFFFL;
        values[26 + valuesStart] = w18 >>> 18 & 0x1FFFFFFFFFFFL;
        values[27 + valuesStart] = (w18 >>> 63 | w19 << 1) & 0x1FFFFFFFFFFFL;
        values[28 + valuesStart] = (w19 >>> 44 | w20 << 20) & 0x1FFFFFFFFFFFL;
        values[29 + valuesStart] = (w20 >>> 25 | w21 << 39) & 0x1FFFFFFFFFFFL;
        values[30 + valuesStart] = w21 >>> 6 & 0x1FFFFFFFFFFFL;
        values[31 + valuesStart] = (w21 >>> 51 | w22 << 13) & 0x1FFFFFFFFFFFL;
        values[32 + valuesStart] = (w22 >>> 32 | w23 << 32) & 0x1FFFFFFFFFFFL;
        values[33 + valuesStart] = w23 >>> 13 & 0x1FFFFFFFFFFFL;
        values[34 + valuesStart] = (w23 >>> 58 | w24 << 6) & 0x1FFFFFFFFFFFL;
        values[35 + valuesStart] = (w24 >>> 39 | w25 << 25) & 0x1FFFFFFFFFFFL;
        values[36 + valuesStart] = (w25 >>> 20 | w26 << 44) & 0x1FFFFFFFFFFFL;
        values[37 + valuesStart] = w26 >>> 1 & 0x1FFFFFFFFFFFL;
        values[38 + valuesStart] = (w26 >>> 46 | w27 << 18) & 0x1FFFFFFFFFFFL;
        values[39 + valuesStart] = (w27 >>> 27 | w28 << 37) & 0x1FFFFFFFFFFFL;
        values[40 + valuesStart] = w28 >>> 8 & 0x1FFFFFFFFFFFL;
        values[41 + valuesStart] = (w28 >>> 53 | w29 << 11) & 0x1FFFFFFFFFFFL;
        values[42 + valuesStart] = (w29 >>> 34 | w30 << 30) & 0x1FFFFFFFFFFFL;
        values[43 + valuesStart] = w30 >>> 15 & 0x1FFFFFFFFFFFL;
        values[44 + valuesStart] = (w30 >>> 60 | w31 << 4) & 0x1FFFFFFFFFFFL;
        values[45 + valuesStart] = (w31 >>> 41 | w32 << 23) & 0x1FFFFFFFFFFFL;
        values[46 + valuesStart] = (w32 >>> 22 | w33 << 42) & 0x1FFFFFFFFFFFL;
        values[47 + valuesStart] = w33 >>> 3 & 0x1FFFFFFFFFFFL;
        values[48 + valuesStart] = (w33 >>> 48 | w34 << 16) & 0x1FFFFFFFFFFFL;
        values[49 + valuesStart] = (w34 >>> 29 | w35 << 35) & 0x1FFFFFFFFFFFL;
        values[50 + valuesStart] = w35 >>> 10 & 0x1FFFFFFFFFFFL;
        values[51 + valuesStart] = (w35 >>> 55 | w36 << 9) & 0x1FFFFFFFFFFFL;
        values[52 + valuesStart] = (w36 >>> 36 | w37 << 28) & 0x1FFFFFFFFFFFL;
        values[53 + valuesStart] = w37 >>> 17 & 0x1FFFFFFFFFFFL;
        values[54 + valuesStart] = (w37 >>> 62 | w38 << 2) & 0x1FFFFFFFFFFFL;
        values[55 + valuesStart] = (w38 >>> 43 | w39 << 21) & 0x1FFFFFFFFFFFL;
        values[56 + valuesStart] = (w39 >>> 24 | w40 << 40) & 0x1FFFFFFFFFFFL;
        values[57 + valuesStart] = w40 >>> 5 & 0x1FFFFFFFFFFFL;
        values[58 + valuesStart] = (w40 >>> 50 | w41 << 14) & 0x1FFFFFFFFFFFL;
        values[59 + valuesStart] = (w41 >>> 31 | w42 << 33) & 0x1FFFFFFFFFFFL;
        values[60 + valuesStart] = w42 >>> 12 & 0x1FFFFFFFFFFFL;
        values[61 + valuesStart] = (w42 >>> 57 | w43 << 7) & 0x1FFFFFFFFFFFL;
        values[62 + valuesStart] = (w43 >>> 38 | w44 << 26) & 0x1FFFFFFFFFFFL;
        values[63 + valuesStart] = w44 >>> 19;
        return 360 + packedPtr;
    }

    /**
     * Unpacks 64 46-bit values using 368 bytes, touching 46 words.
     */
    private static long unpack46(long[] values, int valuesStart, long packedPtr) {
        // Access 46 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 46 | w1 << 18) & 0x3FFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 28 | w2 << 36) & 0x3FFFFFFFFFFFL;
        values[3 + valuesStart] = w2 >>> 10 & 0x3FFFFFFFFFFFL;
        values[4 + valuesStart] = (w2 >>> 56 | w3 << 8) & 0x3FFFFFFFFFFFL;
        values[5 + valuesStart] = (w3 >>> 38 | w4 << 26) & 0x3FFFFFFFFFFFL;
        values[6 + valuesStart] = (w4 >>> 20 | w5 << 44) & 0x3FFFFFFFFFFFL;
        values[7 + valuesStart] = w5 >>> 2 & 0x3FFFFFFFFFFFL;
        values[8 + valuesStart] = (w5 >>> 48 | w6 << 16) & 0x3FFFFFFFFFFFL;
        values[9 + valuesStart] = (w6 >>> 30 | w7 << 34) & 0x3FFFFFFFFFFFL;
        values[10 + valuesStart] = w7 >>> 12 & 0x3FFFFFFFFFFFL;
        values[11 + valuesStart] = (w7 >>> 58 | w8 << 6) & 0x3FFFFFFFFFFFL;
        values[12 + valuesStart] = (w8 >>> 40 | w9 << 24) & 0x3FFFFFFFFFFFL;
        values[13 + valuesStart] = (w9 >>> 22 | w10 << 42) & 0x3FFFFFFFFFFFL;
        values[14 + valuesStart] = w10 >>> 4 & 0x3FFFFFFFFFFFL;
        values[15 + valuesStart] = (w10 >>> 50 | w11 << 14) & 0x3FFFFFFFFFFFL;
        values[16 + valuesStart] = (w11 >>> 32 | w12 << 32) & 0x3FFFFFFFFFFFL;
        values[17 + valuesStart] = w12 >>> 14 & 0x3FFFFFFFFFFFL;
        values[18 + valuesStart] = (w12 >>> 60 | w13 << 4) & 0x3FFFFFFFFFFFL;
        values[19 + valuesStart] = (w13 >>> 42 | w14 << 22) & 0x3FFFFFFFFFFFL;
        values[20 + valuesStart] = (w14 >>> 24 | w15 << 40) & 0x3FFFFFFFFFFFL;
        values[21 + valuesStart] = w15 >>> 6 & 0x3FFFFFFFFFFFL;
        values[22 + valuesStart] = (w15 >>> 52 | w16 << 12) & 0x3FFFFFFFFFFFL;
        values[23 + valuesStart] = (w16 >>> 34 | w17 << 30) & 0x3FFFFFFFFFFFL;
        values[24 + valuesStart] = w17 >>> 16 & 0x3FFFFFFFFFFFL;
        values[25 + valuesStart] = (w17 >>> 62 | w18 << 2) & 0x3FFFFFFFFFFFL;
        values[26 + valuesStart] = (w18 >>> 44 | w19 << 20) & 0x3FFFFFFFFFFFL;
        values[27 + valuesStart] = (w19 >>> 26 | w20 << 38) & 0x3FFFFFFFFFFFL;
        values[28 + valuesStart] = w20 >>> 8 & 0x3FFFFFFFFFFFL;
        values[29 + valuesStart] = (w20 >>> 54 | w21 << 10) & 0x3FFFFFFFFFFFL;
        values[30 + valuesStart] = (w21 >>> 36 | w22 << 28) & 0x3FFFFFFFFFFFL;
        values[31 + valuesStart] = w22 >>> 18;
        values[32 + valuesStart] = w23 & 0x3FFFFFFFFFFFL;
        values[33 + valuesStart] = (w23 >>> 46 | w24 << 18) & 0x3FFFFFFFFFFFL;
        values[34 + valuesStart] = (w24 >>> 28 | w25 << 36) & 0x3FFFFFFFFFFFL;
        values[35 + valuesStart] = w25 >>> 10 & 0x3FFFFFFFFFFFL;
        values[36 + valuesStart] = (w25 >>> 56 | w26 << 8) & 0x3FFFFFFFFFFFL;
        values[37 + valuesStart] = (w26 >>> 38 | w27 << 26) & 0x3FFFFFFFFFFFL;
        values[38 + valuesStart] = (w27 >>> 20 | w28 << 44) & 0x3FFFFFFFFFFFL;
        values[39 + valuesStart] = w28 >>> 2 & 0x3FFFFFFFFFFFL;
        values[40 + valuesStart] = (w28 >>> 48 | w29 << 16) & 0x3FFFFFFFFFFFL;
        values[41 + valuesStart] = (w29 >>> 30 | w30 << 34) & 0x3FFFFFFFFFFFL;
        values[42 + valuesStart] = w30 >>> 12 & 0x3FFFFFFFFFFFL;
        values[43 + valuesStart] = (w30 >>> 58 | w31 << 6) & 0x3FFFFFFFFFFFL;
        values[44 + valuesStart] = (w31 >>> 40 | w32 << 24) & 0x3FFFFFFFFFFFL;
        values[45 + valuesStart] = (w32 >>> 22 | w33 << 42) & 0x3FFFFFFFFFFFL;
        values[46 + valuesStart] = w33 >>> 4 & 0x3FFFFFFFFFFFL;
        values[47 + valuesStart] = (w33 >>> 50 | w34 << 14) & 0x3FFFFFFFFFFFL;
        values[48 + valuesStart] = (w34 >>> 32 | w35 << 32) & 0x3FFFFFFFFFFFL;
        values[49 + valuesStart] = w35 >>> 14 & 0x3FFFFFFFFFFFL;
        values[50 + valuesStart] = (w35 >>> 60 | w36 << 4) & 0x3FFFFFFFFFFFL;
        values[51 + valuesStart] = (w36 >>> 42 | w37 << 22) & 0x3FFFFFFFFFFFL;
        values[52 + valuesStart] = (w37 >>> 24 | w38 << 40) & 0x3FFFFFFFFFFFL;
        values[53 + valuesStart] = w38 >>> 6 & 0x3FFFFFFFFFFFL;
        values[54 + valuesStart] = (w38 >>> 52 | w39 << 12) & 0x3FFFFFFFFFFFL;
        values[55 + valuesStart] = (w39 >>> 34 | w40 << 30) & 0x3FFFFFFFFFFFL;
        values[56 + valuesStart] = w40 >>> 16 & 0x3FFFFFFFFFFFL;
        values[57 + valuesStart] = (w40 >>> 62 | w41 << 2) & 0x3FFFFFFFFFFFL;
        values[58 + valuesStart] = (w41 >>> 44 | w42 << 20) & 0x3FFFFFFFFFFFL;
        values[59 + valuesStart] = (w42 >>> 26 | w43 << 38) & 0x3FFFFFFFFFFFL;
        values[60 + valuesStart] = w43 >>> 8 & 0x3FFFFFFFFFFFL;
        values[61 + valuesStart] = (w43 >>> 54 | w44 << 10) & 0x3FFFFFFFFFFFL;
        values[62 + valuesStart] = (w44 >>> 36 | w45 << 28) & 0x3FFFFFFFFFFFL;
        values[63 + valuesStart] = w45 >>> 18;
        return 368 + packedPtr;
    }

    /**
     * Unpacks 64 47-bit values using 376 bytes, touching 47 words.
     */
    private static long unpack47(long[] values, int valuesStart, long packedPtr) {
        // Access 47 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 47 | w1 << 17) & 0x7FFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 30 | w2 << 34) & 0x7FFFFFFFFFFFL;
        values[3 + valuesStart] = w2 >>> 13 & 0x7FFFFFFFFFFFL;
        values[4 + valuesStart] = (w2 >>> 60 | w3 << 4) & 0x7FFFFFFFFFFFL;
        values[5 + valuesStart] = (w3 >>> 43 | w4 << 21) & 0x7FFFFFFFFFFFL;
        values[6 + valuesStart] = (w4 >>> 26 | w5 << 38) & 0x7FFFFFFFFFFFL;
        values[7 + valuesStart] = w5 >>> 9 & 0x7FFFFFFFFFFFL;
        values[8 + valuesStart] = (w5 >>> 56 | w6 << 8) & 0x7FFFFFFFFFFFL;
        values[9 + valuesStart] = (w6 >>> 39 | w7 << 25) & 0x7FFFFFFFFFFFL;
        values[10 + valuesStart] = (w7 >>> 22 | w8 << 42) & 0x7FFFFFFFFFFFL;
        values[11 + valuesStart] = w8 >>> 5 & 0x7FFFFFFFFFFFL;
        values[12 + valuesStart] = (w8 >>> 52 | w9 << 12) & 0x7FFFFFFFFFFFL;
        values[13 + valuesStart] = (w9 >>> 35 | w10 << 29) & 0x7FFFFFFFFFFFL;
        values[14 + valuesStart] = (w10 >>> 18 | w11 << 46) & 0x7FFFFFFFFFFFL;
        values[15 + valuesStart] = w11 >>> 1 & 0x7FFFFFFFFFFFL;
        values[16 + valuesStart] = (w11 >>> 48 | w12 << 16) & 0x7FFFFFFFFFFFL;
        values[17 + valuesStart] = (w12 >>> 31 | w13 << 33) & 0x7FFFFFFFFFFFL;
        values[18 + valuesStart] = w13 >>> 14 & 0x7FFFFFFFFFFFL;
        values[19 + valuesStart] = (w13 >>> 61 | w14 << 3) & 0x7FFFFFFFFFFFL;
        values[20 + valuesStart] = (w14 >>> 44 | w15 << 20) & 0x7FFFFFFFFFFFL;
        values[21 + valuesStart] = (w15 >>> 27 | w16 << 37) & 0x7FFFFFFFFFFFL;
        values[22 + valuesStart] = w16 >>> 10 & 0x7FFFFFFFFFFFL;
        values[23 + valuesStart] = (w16 >>> 57 | w17 << 7) & 0x7FFFFFFFFFFFL;
        values[24 + valuesStart] = (w17 >>> 40 | w18 << 24) & 0x7FFFFFFFFFFFL;
        values[25 + valuesStart] = (w18 >>> 23 | w19 << 41) & 0x7FFFFFFFFFFFL;
        values[26 + valuesStart] = w19 >>> 6 & 0x7FFFFFFFFFFFL;
        values[27 + valuesStart] = (w19 >>> 53 | w20 << 11) & 0x7FFFFFFFFFFFL;
        values[28 + valuesStart] = (w20 >>> 36 | w21 << 28) & 0x7FFFFFFFFFFFL;
        values[29 + valuesStart] = (w21 >>> 19 | w22 << 45) & 0x7FFFFFFFFFFFL;
        values[30 + valuesStart] = w22 >>> 2 & 0x7FFFFFFFFFFFL;
        values[31 + valuesStart] = (w22 >>> 49 | w23 << 15) & 0x7FFFFFFFFFFFL;
        values[32 + valuesStart] = (w23 >>> 32 | w24 << 32) & 0x7FFFFFFFFFFFL;
        values[33 + valuesStart] = w24 >>> 15 & 0x7FFFFFFFFFFFL;
        values[34 + valuesStart] = (w24 >>> 62 | w25 << 2) & 0x7FFFFFFFFFFFL;
        values[35 + valuesStart] = (w25 >>> 45 | w26 << 19) & 0x7FFFFFFFFFFFL;
        values[36 + valuesStart] = (w26 >>> 28 | w27 << 36) & 0x7FFFFFFFFFFFL;
        values[37 + valuesStart] = w27 >>> 11 & 0x7FFFFFFFFFFFL;
        values[38 + valuesStart] = (w27 >>> 58 | w28 << 6) & 0x7FFFFFFFFFFFL;
        values[39 + valuesStart] = (w28 >>> 41 | w29 << 23) & 0x7FFFFFFFFFFFL;
        values[40 + valuesStart] = (w29 >>> 24 | w30 << 40) & 0x7FFFFFFFFFFFL;
        values[41 + valuesStart] = w30 >>> 7 & 0x7FFFFFFFFFFFL;
        values[42 + valuesStart] = (w30 >>> 54 | w31 << 10) & 0x7FFFFFFFFFFFL;
        values[43 + valuesStart] = (w31 >>> 37 | w32 << 27) & 0x7FFFFFFFFFFFL;
        values[44 + valuesStart] = (w32 >>> 20 | w33 << 44) & 0x7FFFFFFFFFFFL;
        values[45 + valuesStart] = w33 >>> 3 & 0x7FFFFFFFFFFFL;
        values[46 + valuesStart] = (w33 >>> 50 | w34 << 14) & 0x7FFFFFFFFFFFL;
        values[47 + valuesStart] = (w34 >>> 33 | w35 << 31) & 0x7FFFFFFFFFFFL;
        values[48 + valuesStart] = w35 >>> 16 & 0x7FFFFFFFFFFFL;
        values[49 + valuesStart] = (w35 >>> 63 | w36 << 1) & 0x7FFFFFFFFFFFL;
        values[50 + valuesStart] = (w36 >>> 46 | w37 << 18) & 0x7FFFFFFFFFFFL;
        values[51 + valuesStart] = (w37 >>> 29 | w38 << 35) & 0x7FFFFFFFFFFFL;
        values[52 + valuesStart] = w38 >>> 12 & 0x7FFFFFFFFFFFL;
        values[53 + valuesStart] = (w38 >>> 59 | w39 << 5) & 0x7FFFFFFFFFFFL;
        values[54 + valuesStart] = (w39 >>> 42 | w40 << 22) & 0x7FFFFFFFFFFFL;
        values[55 + valuesStart] = (w40 >>> 25 | w41 << 39) & 0x7FFFFFFFFFFFL;
        values[56 + valuesStart] = w41 >>> 8 & 0x7FFFFFFFFFFFL;
        values[57 + valuesStart] = (w41 >>> 55 | w42 << 9) & 0x7FFFFFFFFFFFL;
        values[58 + valuesStart] = (w42 >>> 38 | w43 << 26) & 0x7FFFFFFFFFFFL;
        values[59 + valuesStart] = (w43 >>> 21 | w44 << 43) & 0x7FFFFFFFFFFFL;
        values[60 + valuesStart] = w44 >>> 4 & 0x7FFFFFFFFFFFL;
        values[61 + valuesStart] = (w44 >>> 51 | w45 << 13) & 0x7FFFFFFFFFFFL;
        values[62 + valuesStart] = (w45 >>> 34 | w46 << 30) & 0x7FFFFFFFFFFFL;
        values[63 + valuesStart] = w46 >>> 17;
        return 376 + packedPtr;
    }

    /**
     * Unpacks 64 48-bit values using 384 bytes, touching 48 words.
     */
    private static long unpack48(long[] values, int valuesStart, long packedPtr) {
        // Access 48 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 48 | w1 << 16) & 0xFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 32 | w2 << 32) & 0xFFFFFFFFFFFFL;
        values[3 + valuesStart] = w2 >>> 16;
        values[4 + valuesStart] = w3 & 0xFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w3 >>> 48 | w4 << 16) & 0xFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w4 >>> 32 | w5 << 32) & 0xFFFFFFFFFFFFL;
        values[7 + valuesStart] = w5 >>> 16;
        values[8 + valuesStart] = w6 & 0xFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w6 >>> 48 | w7 << 16) & 0xFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w7 >>> 32 | w8 << 32) & 0xFFFFFFFFFFFFL;
        values[11 + valuesStart] = w8 >>> 16;
        values[12 + valuesStart] = w9 & 0xFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w9 >>> 48 | w10 << 16) & 0xFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w10 >>> 32 | w11 << 32) & 0xFFFFFFFFFFFFL;
        values[15 + valuesStart] = w11 >>> 16;
        values[16 + valuesStart] = w12 & 0xFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w12 >>> 48 | w13 << 16) & 0xFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w13 >>> 32 | w14 << 32) & 0xFFFFFFFFFFFFL;
        values[19 + valuesStart] = w14 >>> 16;
        values[20 + valuesStart] = w15 & 0xFFFFFFFFFFFFL;
        values[21 + valuesStart] = (w15 >>> 48 | w16 << 16) & 0xFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w16 >>> 32 | w17 << 32) & 0xFFFFFFFFFFFFL;
        values[23 + valuesStart] = w17 >>> 16;
        values[24 + valuesStart] = w18 & 0xFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w18 >>> 48 | w19 << 16) & 0xFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w19 >>> 32 | w20 << 32) & 0xFFFFFFFFFFFFL;
        values[27 + valuesStart] = w20 >>> 16;
        values[28 + valuesStart] = w21 & 0xFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w21 >>> 48 | w22 << 16) & 0xFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w22 >>> 32 | w23 << 32) & 0xFFFFFFFFFFFFL;
        values[31 + valuesStart] = w23 >>> 16;
        values[32 + valuesStart] = w24 & 0xFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w24 >>> 48 | w25 << 16) & 0xFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w25 >>> 32 | w26 << 32) & 0xFFFFFFFFFFFFL;
        values[35 + valuesStart] = w26 >>> 16;
        values[36 + valuesStart] = w27 & 0xFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w27 >>> 48 | w28 << 16) & 0xFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w28 >>> 32 | w29 << 32) & 0xFFFFFFFFFFFFL;
        values[39 + valuesStart] = w29 >>> 16;
        values[40 + valuesStart] = w30 & 0xFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w30 >>> 48 | w31 << 16) & 0xFFFFFFFFFFFFL;
        values[42 + valuesStart] = (w31 >>> 32 | w32 << 32) & 0xFFFFFFFFFFFFL;
        values[43 + valuesStart] = w32 >>> 16;
        values[44 + valuesStart] = w33 & 0xFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w33 >>> 48 | w34 << 16) & 0xFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w34 >>> 32 | w35 << 32) & 0xFFFFFFFFFFFFL;
        values[47 + valuesStart] = w35 >>> 16;
        values[48 + valuesStart] = w36 & 0xFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w36 >>> 48 | w37 << 16) & 0xFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w37 >>> 32 | w38 << 32) & 0xFFFFFFFFFFFFL;
        values[51 + valuesStart] = w38 >>> 16;
        values[52 + valuesStart] = w39 & 0xFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w39 >>> 48 | w40 << 16) & 0xFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w40 >>> 32 | w41 << 32) & 0xFFFFFFFFFFFFL;
        values[55 + valuesStart] = w41 >>> 16;
        values[56 + valuesStart] = w42 & 0xFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w42 >>> 48 | w43 << 16) & 0xFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w43 >>> 32 | w44 << 32) & 0xFFFFFFFFFFFFL;
        values[59 + valuesStart] = w44 >>> 16;
        values[60 + valuesStart] = w45 & 0xFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w45 >>> 48 | w46 << 16) & 0xFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w46 >>> 32 | w47 << 32) & 0xFFFFFFFFFFFFL;
        values[63 + valuesStart] = w47 >>> 16;
        return 384 + packedPtr;
    }

    /**
     * Unpacks 64 49-bit values using 392 bytes, touching 49 words.
     */
    private static long unpack49(long[] values, int valuesStart, long packedPtr) {
        // Access 49 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 49 | w1 << 15) & 0x1FFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 34 | w2 << 30) & 0x1FFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 19 | w3 << 45) & 0x1FFFFFFFFFFFFL;
        values[4 + valuesStart] = w3 >>> 4 & 0x1FFFFFFFFFFFFL;
        values[5 + valuesStart] = (w3 >>> 53 | w4 << 11) & 0x1FFFFFFFFFFFFL;
        values[6 + valuesStart] = (w4 >>> 38 | w5 << 26) & 0x1FFFFFFFFFFFFL;
        values[7 + valuesStart] = (w5 >>> 23 | w6 << 41) & 0x1FFFFFFFFFFFFL;
        values[8 + valuesStart] = w6 >>> 8 & 0x1FFFFFFFFFFFFL;
        values[9 + valuesStart] = (w6 >>> 57 | w7 << 7) & 0x1FFFFFFFFFFFFL;
        values[10 + valuesStart] = (w7 >>> 42 | w8 << 22) & 0x1FFFFFFFFFFFFL;
        values[11 + valuesStart] = (w8 >>> 27 | w9 << 37) & 0x1FFFFFFFFFFFFL;
        values[12 + valuesStart] = w9 >>> 12 & 0x1FFFFFFFFFFFFL;
        values[13 + valuesStart] = (w9 >>> 61 | w10 << 3) & 0x1FFFFFFFFFFFFL;
        values[14 + valuesStart] = (w10 >>> 46 | w11 << 18) & 0x1FFFFFFFFFFFFL;
        values[15 + valuesStart] = (w11 >>> 31 | w12 << 33) & 0x1FFFFFFFFFFFFL;
        values[16 + valuesStart] = (w12 >>> 16 | w13 << 48) & 0x1FFFFFFFFFFFFL;
        values[17 + valuesStart] = w13 >>> 1 & 0x1FFFFFFFFFFFFL;
        values[18 + valuesStart] = (w13 >>> 50 | w14 << 14) & 0x1FFFFFFFFFFFFL;
        values[19 + valuesStart] = (w14 >>> 35 | w15 << 29) & 0x1FFFFFFFFFFFFL;
        values[20 + valuesStart] = (w15 >>> 20 | w16 << 44) & 0x1FFFFFFFFFFFFL;
        values[21 + valuesStart] = w16 >>> 5 & 0x1FFFFFFFFFFFFL;
        values[22 + valuesStart] = (w16 >>> 54 | w17 << 10) & 0x1FFFFFFFFFFFFL;
        values[23 + valuesStart] = (w17 >>> 39 | w18 << 25) & 0x1FFFFFFFFFFFFL;
        values[24 + valuesStart] = (w18 >>> 24 | w19 << 40) & 0x1FFFFFFFFFFFFL;
        values[25 + valuesStart] = w19 >>> 9 & 0x1FFFFFFFFFFFFL;
        values[26 + valuesStart] = (w19 >>> 58 | w20 << 6) & 0x1FFFFFFFFFFFFL;
        values[27 + valuesStart] = (w20 >>> 43 | w21 << 21) & 0x1FFFFFFFFFFFFL;
        values[28 + valuesStart] = (w21 >>> 28 | w22 << 36) & 0x1FFFFFFFFFFFFL;
        values[29 + valuesStart] = w22 >>> 13 & 0x1FFFFFFFFFFFFL;
        values[30 + valuesStart] = (w22 >>> 62 | w23 << 2) & 0x1FFFFFFFFFFFFL;
        values[31 + valuesStart] = (w23 >>> 47 | w24 << 17) & 0x1FFFFFFFFFFFFL;
        values[32 + valuesStart] = (w24 >>> 32 | w25 << 32) & 0x1FFFFFFFFFFFFL;
        values[33 + valuesStart] = (w25 >>> 17 | w26 << 47) & 0x1FFFFFFFFFFFFL;
        values[34 + valuesStart] = w26 >>> 2 & 0x1FFFFFFFFFFFFL;
        values[35 + valuesStart] = (w26 >>> 51 | w27 << 13) & 0x1FFFFFFFFFFFFL;
        values[36 + valuesStart] = (w27 >>> 36 | w28 << 28) & 0x1FFFFFFFFFFFFL;
        values[37 + valuesStart] = (w28 >>> 21 | w29 << 43) & 0x1FFFFFFFFFFFFL;
        values[38 + valuesStart] = w29 >>> 6 & 0x1FFFFFFFFFFFFL;
        values[39 + valuesStart] = (w29 >>> 55 | w30 << 9) & 0x1FFFFFFFFFFFFL;
        values[40 + valuesStart] = (w30 >>> 40 | w31 << 24) & 0x1FFFFFFFFFFFFL;
        values[41 + valuesStart] = (w31 >>> 25 | w32 << 39) & 0x1FFFFFFFFFFFFL;
        values[42 + valuesStart] = w32 >>> 10 & 0x1FFFFFFFFFFFFL;
        values[43 + valuesStart] = (w32 >>> 59 | w33 << 5) & 0x1FFFFFFFFFFFFL;
        values[44 + valuesStart] = (w33 >>> 44 | w34 << 20) & 0x1FFFFFFFFFFFFL;
        values[45 + valuesStart] = (w34 >>> 29 | w35 << 35) & 0x1FFFFFFFFFFFFL;
        values[46 + valuesStart] = w35 >>> 14 & 0x1FFFFFFFFFFFFL;
        values[47 + valuesStart] = (w35 >>> 63 | w36 << 1) & 0x1FFFFFFFFFFFFL;
        values[48 + valuesStart] = (w36 >>> 48 | w37 << 16) & 0x1FFFFFFFFFFFFL;
        values[49 + valuesStart] = (w37 >>> 33 | w38 << 31) & 0x1FFFFFFFFFFFFL;
        values[50 + valuesStart] = (w38 >>> 18 | w39 << 46) & 0x1FFFFFFFFFFFFL;
        values[51 + valuesStart] = w39 >>> 3 & 0x1FFFFFFFFFFFFL;
        values[52 + valuesStart] = (w39 >>> 52 | w40 << 12) & 0x1FFFFFFFFFFFFL;
        values[53 + valuesStart] = (w40 >>> 37 | w41 << 27) & 0x1FFFFFFFFFFFFL;
        values[54 + valuesStart] = (w41 >>> 22 | w42 << 42) & 0x1FFFFFFFFFFFFL;
        values[55 + valuesStart] = w42 >>> 7 & 0x1FFFFFFFFFFFFL;
        values[56 + valuesStart] = (w42 >>> 56 | w43 << 8) & 0x1FFFFFFFFFFFFL;
        values[57 + valuesStart] = (w43 >>> 41 | w44 << 23) & 0x1FFFFFFFFFFFFL;
        values[58 + valuesStart] = (w44 >>> 26 | w45 << 38) & 0x1FFFFFFFFFFFFL;
        values[59 + valuesStart] = w45 >>> 11 & 0x1FFFFFFFFFFFFL;
        values[60 + valuesStart] = (w45 >>> 60 | w46 << 4) & 0x1FFFFFFFFFFFFL;
        values[61 + valuesStart] = (w46 >>> 45 | w47 << 19) & 0x1FFFFFFFFFFFFL;
        values[62 + valuesStart] = (w47 >>> 30 | w48 << 34) & 0x1FFFFFFFFFFFFL;
        values[63 + valuesStart] = w48 >>> 15;
        return 392 + packedPtr;
    }

    /**
     * Unpacks 64 50-bit values using 400 bytes, touching 50 words.
     */
    private static long unpack50(long[] values, int valuesStart, long packedPtr) {
        // Access 50 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 50 | w1 << 14) & 0x3FFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 36 | w2 << 28) & 0x3FFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 22 | w3 << 42) & 0x3FFFFFFFFFFFFL;
        values[4 + valuesStart] = w3 >>> 8 & 0x3FFFFFFFFFFFFL;
        values[5 + valuesStart] = (w3 >>> 58 | w4 << 6) & 0x3FFFFFFFFFFFFL;
        values[6 + valuesStart] = (w4 >>> 44 | w5 << 20) & 0x3FFFFFFFFFFFFL;
        values[7 + valuesStart] = (w5 >>> 30 | w6 << 34) & 0x3FFFFFFFFFFFFL;
        values[8 + valuesStart] = (w6 >>> 16 | w7 << 48) & 0x3FFFFFFFFFFFFL;
        values[9 + valuesStart] = w7 >>> 2 & 0x3FFFFFFFFFFFFL;
        values[10 + valuesStart] = (w7 >>> 52 | w8 << 12) & 0x3FFFFFFFFFFFFL;
        values[11 + valuesStart] = (w8 >>> 38 | w9 << 26) & 0x3FFFFFFFFFFFFL;
        values[12 + valuesStart] = (w9 >>> 24 | w10 << 40) & 0x3FFFFFFFFFFFFL;
        values[13 + valuesStart] = w10 >>> 10 & 0x3FFFFFFFFFFFFL;
        values[14 + valuesStart] = (w10 >>> 60 | w11 << 4) & 0x3FFFFFFFFFFFFL;
        values[15 + valuesStart] = (w11 >>> 46 | w12 << 18) & 0x3FFFFFFFFFFFFL;
        values[16 + valuesStart] = (w12 >>> 32 | w13 << 32) & 0x3FFFFFFFFFFFFL;
        values[17 + valuesStart] = (w13 >>> 18 | w14 << 46) & 0x3FFFFFFFFFFFFL;
        values[18 + valuesStart] = w14 >>> 4 & 0x3FFFFFFFFFFFFL;
        values[19 + valuesStart] = (w14 >>> 54 | w15 << 10) & 0x3FFFFFFFFFFFFL;
        values[20 + valuesStart] = (w15 >>> 40 | w16 << 24) & 0x3FFFFFFFFFFFFL;
        values[21 + valuesStart] = (w16 >>> 26 | w17 << 38) & 0x3FFFFFFFFFFFFL;
        values[22 + valuesStart] = w17 >>> 12 & 0x3FFFFFFFFFFFFL;
        values[23 + valuesStart] = (w17 >>> 62 | w18 << 2) & 0x3FFFFFFFFFFFFL;
        values[24 + valuesStart] = (w18 >>> 48 | w19 << 16) & 0x3FFFFFFFFFFFFL;
        values[25 + valuesStart] = (w19 >>> 34 | w20 << 30) & 0x3FFFFFFFFFFFFL;
        values[26 + valuesStart] = (w20 >>> 20 | w21 << 44) & 0x3FFFFFFFFFFFFL;
        values[27 + valuesStart] = w21 >>> 6 & 0x3FFFFFFFFFFFFL;
        values[28 + valuesStart] = (w21 >>> 56 | w22 << 8) & 0x3FFFFFFFFFFFFL;
        values[29 + valuesStart] = (w22 >>> 42 | w23 << 22) & 0x3FFFFFFFFFFFFL;
        values[30 + valuesStart] = (w23 >>> 28 | w24 << 36) & 0x3FFFFFFFFFFFFL;
        values[31 + valuesStart] = w24 >>> 14;
        values[32 + valuesStart] = w25 & 0x3FFFFFFFFFFFFL;
        values[33 + valuesStart] = (w25 >>> 50 | w26 << 14) & 0x3FFFFFFFFFFFFL;
        values[34 + valuesStart] = (w26 >>> 36 | w27 << 28) & 0x3FFFFFFFFFFFFL;
        values[35 + valuesStart] = (w27 >>> 22 | w28 << 42) & 0x3FFFFFFFFFFFFL;
        values[36 + valuesStart] = w28 >>> 8 & 0x3FFFFFFFFFFFFL;
        values[37 + valuesStart] = (w28 >>> 58 | w29 << 6) & 0x3FFFFFFFFFFFFL;
        values[38 + valuesStart] = (w29 >>> 44 | w30 << 20) & 0x3FFFFFFFFFFFFL;
        values[39 + valuesStart] = (w30 >>> 30 | w31 << 34) & 0x3FFFFFFFFFFFFL;
        values[40 + valuesStart] = (w31 >>> 16 | w32 << 48) & 0x3FFFFFFFFFFFFL;
        values[41 + valuesStart] = w32 >>> 2 & 0x3FFFFFFFFFFFFL;
        values[42 + valuesStart] = (w32 >>> 52 | w33 << 12) & 0x3FFFFFFFFFFFFL;
        values[43 + valuesStart] = (w33 >>> 38 | w34 << 26) & 0x3FFFFFFFFFFFFL;
        values[44 + valuesStart] = (w34 >>> 24 | w35 << 40) & 0x3FFFFFFFFFFFFL;
        values[45 + valuesStart] = w35 >>> 10 & 0x3FFFFFFFFFFFFL;
        values[46 + valuesStart] = (w35 >>> 60 | w36 << 4) & 0x3FFFFFFFFFFFFL;
        values[47 + valuesStart] = (w36 >>> 46 | w37 << 18) & 0x3FFFFFFFFFFFFL;
        values[48 + valuesStart] = (w37 >>> 32 | w38 << 32) & 0x3FFFFFFFFFFFFL;
        values[49 + valuesStart] = (w38 >>> 18 | w39 << 46) & 0x3FFFFFFFFFFFFL;
        values[50 + valuesStart] = w39 >>> 4 & 0x3FFFFFFFFFFFFL;
        values[51 + valuesStart] = (w39 >>> 54 | w40 << 10) & 0x3FFFFFFFFFFFFL;
        values[52 + valuesStart] = (w40 >>> 40 | w41 << 24) & 0x3FFFFFFFFFFFFL;
        values[53 + valuesStart] = (w41 >>> 26 | w42 << 38) & 0x3FFFFFFFFFFFFL;
        values[54 + valuesStart] = w42 >>> 12 & 0x3FFFFFFFFFFFFL;
        values[55 + valuesStart] = (w42 >>> 62 | w43 << 2) & 0x3FFFFFFFFFFFFL;
        values[56 + valuesStart] = (w43 >>> 48 | w44 << 16) & 0x3FFFFFFFFFFFFL;
        values[57 + valuesStart] = (w44 >>> 34 | w45 << 30) & 0x3FFFFFFFFFFFFL;
        values[58 + valuesStart] = (w45 >>> 20 | w46 << 44) & 0x3FFFFFFFFFFFFL;
        values[59 + valuesStart] = w46 >>> 6 & 0x3FFFFFFFFFFFFL;
        values[60 + valuesStart] = (w46 >>> 56 | w47 << 8) & 0x3FFFFFFFFFFFFL;
        values[61 + valuesStart] = (w47 >>> 42 | w48 << 22) & 0x3FFFFFFFFFFFFL;
        values[62 + valuesStart] = (w48 >>> 28 | w49 << 36) & 0x3FFFFFFFFFFFFL;
        values[63 + valuesStart] = w49 >>> 14;
        return 400 + packedPtr;
    }

    /**
     * Unpacks 64 51-bit values using 408 bytes, touching 51 words.
     */
    private static long unpack51(long[] values, int valuesStart, long packedPtr) {
        // Access 51 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 51 | w1 << 13) & 0x7FFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 38 | w2 << 26) & 0x7FFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 25 | w3 << 39) & 0x7FFFFFFFFFFFFL;
        values[4 + valuesStart] = w3 >>> 12 & 0x7FFFFFFFFFFFFL;
        values[5 + valuesStart] = (w3 >>> 63 | w4 << 1) & 0x7FFFFFFFFFFFFL;
        values[6 + valuesStart] = (w4 >>> 50 | w5 << 14) & 0x7FFFFFFFFFFFFL;
        values[7 + valuesStart] = (w5 >>> 37 | w6 << 27) & 0x7FFFFFFFFFFFFL;
        values[8 + valuesStart] = (w6 >>> 24 | w7 << 40) & 0x7FFFFFFFFFFFFL;
        values[9 + valuesStart] = w7 >>> 11 & 0x7FFFFFFFFFFFFL;
        values[10 + valuesStart] = (w7 >>> 62 | w8 << 2) & 0x7FFFFFFFFFFFFL;
        values[11 + valuesStart] = (w8 >>> 49 | w9 << 15) & 0x7FFFFFFFFFFFFL;
        values[12 + valuesStart] = (w9 >>> 36 | w10 << 28) & 0x7FFFFFFFFFFFFL;
        values[13 + valuesStart] = (w10 >>> 23 | w11 << 41) & 0x7FFFFFFFFFFFFL;
        values[14 + valuesStart] = w11 >>> 10 & 0x7FFFFFFFFFFFFL;
        values[15 + valuesStart] = (w11 >>> 61 | w12 << 3) & 0x7FFFFFFFFFFFFL;
        values[16 + valuesStart] = (w12 >>> 48 | w13 << 16) & 0x7FFFFFFFFFFFFL;
        values[17 + valuesStart] = (w13 >>> 35 | w14 << 29) & 0x7FFFFFFFFFFFFL;
        values[18 + valuesStart] = (w14 >>> 22 | w15 << 42) & 0x7FFFFFFFFFFFFL;
        values[19 + valuesStart] = w15 >>> 9 & 0x7FFFFFFFFFFFFL;
        values[20 + valuesStart] = (w15 >>> 60 | w16 << 4) & 0x7FFFFFFFFFFFFL;
        values[21 + valuesStart] = (w16 >>> 47 | w17 << 17) & 0x7FFFFFFFFFFFFL;
        values[22 + valuesStart] = (w17 >>> 34 | w18 << 30) & 0x7FFFFFFFFFFFFL;
        values[23 + valuesStart] = (w18 >>> 21 | w19 << 43) & 0x7FFFFFFFFFFFFL;
        values[24 + valuesStart] = w19 >>> 8 & 0x7FFFFFFFFFFFFL;
        values[25 + valuesStart] = (w19 >>> 59 | w20 << 5) & 0x7FFFFFFFFFFFFL;
        values[26 + valuesStart] = (w20 >>> 46 | w21 << 18) & 0x7FFFFFFFFFFFFL;
        values[27 + valuesStart] = (w21 >>> 33 | w22 << 31) & 0x7FFFFFFFFFFFFL;
        values[28 + valuesStart] = (w22 >>> 20 | w23 << 44) & 0x7FFFFFFFFFFFFL;
        values[29 + valuesStart] = w23 >>> 7 & 0x7FFFFFFFFFFFFL;
        values[30 + valuesStart] = (w23 >>> 58 | w24 << 6) & 0x7FFFFFFFFFFFFL;
        values[31 + valuesStart] = (w24 >>> 45 | w25 << 19) & 0x7FFFFFFFFFFFFL;
        values[32 + valuesStart] = (w25 >>> 32 | w26 << 32) & 0x7FFFFFFFFFFFFL;
        values[33 + valuesStart] = (w26 >>> 19 | w27 << 45) & 0x7FFFFFFFFFFFFL;
        values[34 + valuesStart] = w27 >>> 6 & 0x7FFFFFFFFFFFFL;
        values[35 + valuesStart] = (w27 >>> 57 | w28 << 7) & 0x7FFFFFFFFFFFFL;
        values[36 + valuesStart] = (w28 >>> 44 | w29 << 20) & 0x7FFFFFFFFFFFFL;
        values[37 + valuesStart] = (w29 >>> 31 | w30 << 33) & 0x7FFFFFFFFFFFFL;
        values[38 + valuesStart] = (w30 >>> 18 | w31 << 46) & 0x7FFFFFFFFFFFFL;
        values[39 + valuesStart] = w31 >>> 5 & 0x7FFFFFFFFFFFFL;
        values[40 + valuesStart] = (w31 >>> 56 | w32 << 8) & 0x7FFFFFFFFFFFFL;
        values[41 + valuesStart] = (w32 >>> 43 | w33 << 21) & 0x7FFFFFFFFFFFFL;
        values[42 + valuesStart] = (w33 >>> 30 | w34 << 34) & 0x7FFFFFFFFFFFFL;
        values[43 + valuesStart] = (w34 >>> 17 | w35 << 47) & 0x7FFFFFFFFFFFFL;
        values[44 + valuesStart] = w35 >>> 4 & 0x7FFFFFFFFFFFFL;
        values[45 + valuesStart] = (w35 >>> 55 | w36 << 9) & 0x7FFFFFFFFFFFFL;
        values[46 + valuesStart] = (w36 >>> 42 | w37 << 22) & 0x7FFFFFFFFFFFFL;
        values[47 + valuesStart] = (w37 >>> 29 | w38 << 35) & 0x7FFFFFFFFFFFFL;
        values[48 + valuesStart] = (w38 >>> 16 | w39 << 48) & 0x7FFFFFFFFFFFFL;
        values[49 + valuesStart] = w39 >>> 3 & 0x7FFFFFFFFFFFFL;
        values[50 + valuesStart] = (w39 >>> 54 | w40 << 10) & 0x7FFFFFFFFFFFFL;
        values[51 + valuesStart] = (w40 >>> 41 | w41 << 23) & 0x7FFFFFFFFFFFFL;
        values[52 + valuesStart] = (w41 >>> 28 | w42 << 36) & 0x7FFFFFFFFFFFFL;
        values[53 + valuesStart] = (w42 >>> 15 | w43 << 49) & 0x7FFFFFFFFFFFFL;
        values[54 + valuesStart] = w43 >>> 2 & 0x7FFFFFFFFFFFFL;
        values[55 + valuesStart] = (w43 >>> 53 | w44 << 11) & 0x7FFFFFFFFFFFFL;
        values[56 + valuesStart] = (w44 >>> 40 | w45 << 24) & 0x7FFFFFFFFFFFFL;
        values[57 + valuesStart] = (w45 >>> 27 | w46 << 37) & 0x7FFFFFFFFFFFFL;
        values[58 + valuesStart] = (w46 >>> 14 | w47 << 50) & 0x7FFFFFFFFFFFFL;
        values[59 + valuesStart] = w47 >>> 1 & 0x7FFFFFFFFFFFFL;
        values[60 + valuesStart] = (w47 >>> 52 | w48 << 12) & 0x7FFFFFFFFFFFFL;
        values[61 + valuesStart] = (w48 >>> 39 | w49 << 25) & 0x7FFFFFFFFFFFFL;
        values[62 + valuesStart] = (w49 >>> 26 | w50 << 38) & 0x7FFFFFFFFFFFFL;
        values[63 + valuesStart] = w50 >>> 13;
        return 408 + packedPtr;
    }

    /**
     * Unpacks 64 52-bit values using 416 bytes, touching 52 words.
     */
    private static long unpack52(long[] values, int valuesStart, long packedPtr) {
        // Access 52 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 52 | w1 << 12) & 0xFFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 40 | w2 << 24) & 0xFFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 28 | w3 << 36) & 0xFFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 16 | w4 << 48) & 0xFFFFFFFFFFFFFL;
        values[5 + valuesStart] = w4 >>> 4 & 0xFFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w4 >>> 56 | w5 << 8) & 0xFFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w5 >>> 44 | w6 << 20) & 0xFFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w6 >>> 32 | w7 << 32) & 0xFFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w7 >>> 20 | w8 << 44) & 0xFFFFFFFFFFFFFL;
        values[10 + valuesStart] = w8 >>> 8 & 0xFFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w8 >>> 60 | w9 << 4) & 0xFFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w9 >>> 48 | w10 << 16) & 0xFFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w10 >>> 36 | w11 << 28) & 0xFFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w11 >>> 24 | w12 << 40) & 0xFFFFFFFFFFFFFL;
        values[15 + valuesStart] = w12 >>> 12;
        values[16 + valuesStart] = w13 & 0xFFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w13 >>> 52 | w14 << 12) & 0xFFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w14 >>> 40 | w15 << 24) & 0xFFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w15 >>> 28 | w16 << 36) & 0xFFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w16 >>> 16 | w17 << 48) & 0xFFFFFFFFFFFFFL;
        values[21 + valuesStart] = w17 >>> 4 & 0xFFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w17 >>> 56 | w18 << 8) & 0xFFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w18 >>> 44 | w19 << 20) & 0xFFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w19 >>> 32 | w20 << 32) & 0xFFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w20 >>> 20 | w21 << 44) & 0xFFFFFFFFFFFFFL;
        values[26 + valuesStart] = w21 >>> 8 & 0xFFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w21 >>> 60 | w22 << 4) & 0xFFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w22 >>> 48 | w23 << 16) & 0xFFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w23 >>> 36 | w24 << 28) & 0xFFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w24 >>> 24 | w25 << 40) & 0xFFFFFFFFFFFFFL;
        values[31 + valuesStart] = w25 >>> 12;
        values[32 + valuesStart] = w26 & 0xFFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w26 >>> 52 | w27 << 12) & 0xFFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w27 >>> 40 | w28 << 24) & 0xFFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w28 >>> 28 | w29 << 36) & 0xFFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w29 >>> 16 | w30 << 48) & 0xFFFFFFFFFFFFFL;
        values[37 + valuesStart] = w30 >>> 4 & 0xFFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w30 >>> 56 | w31 << 8) & 0xFFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w31 >>> 44 | w32 << 20) & 0xFFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w32 >>> 32 | w33 << 32) & 0xFFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w33 >>> 20 | w34 << 44) & 0xFFFFFFFFFFFFFL;
        values[42 + valuesStart] = w34 >>> 8 & 0xFFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w34 >>> 60 | w35 << 4) & 0xFFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w35 >>> 48 | w36 << 16) & 0xFFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w36 >>> 36 | w37 << 28) & 0xFFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w37 >>> 24 | w38 << 40) & 0xFFFFFFFFFFFFFL;
        values[47 + valuesStart] = w38 >>> 12;
        values[48 + valuesStart] = w39 & 0xFFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w39 >>> 52 | w40 << 12) & 0xFFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w40 >>> 40 | w41 << 24) & 0xFFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w41 >>> 28 | w42 << 36) & 0xFFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w42 >>> 16 | w43 << 48) & 0xFFFFFFFFFFFFFL;
        values[53 + valuesStart] = w43 >>> 4 & 0xFFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w43 >>> 56 | w44 << 8) & 0xFFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w44 >>> 44 | w45 << 20) & 0xFFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w45 >>> 32 | w46 << 32) & 0xFFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w46 >>> 20 | w47 << 44) & 0xFFFFFFFFFFFFFL;
        values[58 + valuesStart] = w47 >>> 8 & 0xFFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w47 >>> 60 | w48 << 4) & 0xFFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w48 >>> 48 | w49 << 16) & 0xFFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w49 >>> 36 | w50 << 28) & 0xFFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w50 >>> 24 | w51 << 40) & 0xFFFFFFFFFFFFFL;
        values[63 + valuesStart] = w51 >>> 12;
        return 416 + packedPtr;
    }

    /**
     * Unpacks 64 53-bit values using 424 bytes, touching 53 words.
     */
    private static long unpack53(long[] values, int valuesStart, long packedPtr) {
        // Access 53 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 53 | w1 << 11) & 0x1FFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 42 | w2 << 22) & 0x1FFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 31 | w3 << 33) & 0x1FFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 20 | w4 << 44) & 0x1FFFFFFFFFFFFFL;
        values[5 + valuesStart] = w4 >>> 9 & 0x1FFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w4 >>> 62 | w5 << 2) & 0x1FFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w5 >>> 51 | w6 << 13) & 0x1FFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w6 >>> 40 | w7 << 24) & 0x1FFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w7 >>> 29 | w8 << 35) & 0x1FFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w8 >>> 18 | w9 << 46) & 0x1FFFFFFFFFFFFFL;
        values[11 + valuesStart] = w9 >>> 7 & 0x1FFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w9 >>> 60 | w10 << 4) & 0x1FFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w10 >>> 49 | w11 << 15) & 0x1FFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w11 >>> 38 | w12 << 26) & 0x1FFFFFFFFFFFFFL;
        values[15 + valuesStart] = (w12 >>> 27 | w13 << 37) & 0x1FFFFFFFFFFFFFL;
        values[16 + valuesStart] = (w13 >>> 16 | w14 << 48) & 0x1FFFFFFFFFFFFFL;
        values[17 + valuesStart] = w14 >>> 5 & 0x1FFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w14 >>> 58 | w15 << 6) & 0x1FFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w15 >>> 47 | w16 << 17) & 0x1FFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w16 >>> 36 | w17 << 28) & 0x1FFFFFFFFFFFFFL;
        values[21 + valuesStart] = (w17 >>> 25 | w18 << 39) & 0x1FFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w18 >>> 14 | w19 << 50) & 0x1FFFFFFFFFFFFFL;
        values[23 + valuesStart] = w19 >>> 3 & 0x1FFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w19 >>> 56 | w20 << 8) & 0x1FFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w20 >>> 45 | w21 << 19) & 0x1FFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w21 >>> 34 | w22 << 30) & 0x1FFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w22 >>> 23 | w23 << 41) & 0x1FFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w23 >>> 12 | w24 << 52) & 0x1FFFFFFFFFFFFFL;
        values[29 + valuesStart] = w24 >>> 1 & 0x1FFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w24 >>> 54 | w25 << 10) & 0x1FFFFFFFFFFFFFL;
        values[31 + valuesStart] = (w25 >>> 43 | w26 << 21) & 0x1FFFFFFFFFFFFFL;
        values[32 + valuesStart] = (w26 >>> 32 | w27 << 32) & 0x1FFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w27 >>> 21 | w28 << 43) & 0x1FFFFFFFFFFFFFL;
        values[34 + valuesStart] = w28 >>> 10 & 0x1FFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w28 >>> 63 | w29 << 1) & 0x1FFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w29 >>> 52 | w30 << 12) & 0x1FFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w30 >>> 41 | w31 << 23) & 0x1FFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w31 >>> 30 | w32 << 34) & 0x1FFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w32 >>> 19 | w33 << 45) & 0x1FFFFFFFFFFFFFL;
        values[40 + valuesStart] = w33 >>> 8 & 0x1FFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w33 >>> 61 | w34 << 3) & 0x1FFFFFFFFFFFFFL;
        values[42 + valuesStart] = (w34 >>> 50 | w35 << 14) & 0x1FFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w35 >>> 39 | w36 << 25) & 0x1FFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w36 >>> 28 | w37 << 36) & 0x1FFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w37 >>> 17 | w38 << 47) & 0x1FFFFFFFFFFFFFL;
        values[46 + valuesStart] = w38 >>> 6 & 0x1FFFFFFFFFFFFFL;
        values[47 + valuesStart] = (w38 >>> 59 | w39 << 5) & 0x1FFFFFFFFFFFFFL;
        values[48 + valuesStart] = (w39 >>> 48 | w40 << 16) & 0x1FFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w40 >>> 37 | w41 << 27) & 0x1FFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w41 >>> 26 | w42 << 38) & 0x1FFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w42 >>> 15 | w43 << 49) & 0x1FFFFFFFFFFFFFL;
        values[52 + valuesStart] = w43 >>> 4 & 0x1FFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w43 >>> 57 | w44 << 7) & 0x1FFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w44 >>> 46 | w45 << 18) & 0x1FFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w45 >>> 35 | w46 << 29) & 0x1FFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w46 >>> 24 | w47 << 40) & 0x1FFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w47 >>> 13 | w48 << 51) & 0x1FFFFFFFFFFFFFL;
        values[58 + valuesStart] = w48 >>> 2 & 0x1FFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w48 >>> 55 | w49 << 9) & 0x1FFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w49 >>> 44 | w50 << 20) & 0x1FFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w50 >>> 33 | w51 << 31) & 0x1FFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w51 >>> 22 | w52 << 42) & 0x1FFFFFFFFFFFFFL;
        values[63 + valuesStart] = w52 >>> 11;
        return 424 + packedPtr;
    }

    /**
     * Unpacks 64 54-bit values using 432 bytes, touching 54 words.
     */
    private static long unpack54(long[] values, int valuesStart, long packedPtr) {
        // Access 54 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 54 | w1 << 10) & 0x3FFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 44 | w2 << 20) & 0x3FFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 34 | w3 << 30) & 0x3FFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 24 | w4 << 40) & 0x3FFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 14 | w5 << 50) & 0x3FFFFFFFFFFFFFL;
        values[6 + valuesStart] = w5 >>> 4 & 0x3FFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w5 >>> 58 | w6 << 6) & 0x3FFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w6 >>> 48 | w7 << 16) & 0x3FFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w7 >>> 38 | w8 << 26) & 0x3FFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w8 >>> 28 | w9 << 36) & 0x3FFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w9 >>> 18 | w10 << 46) & 0x3FFFFFFFFFFFFFL;
        values[12 + valuesStart] = w10 >>> 8 & 0x3FFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w10 >>> 62 | w11 << 2) & 0x3FFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w11 >>> 52 | w12 << 12) & 0x3FFFFFFFFFFFFFL;
        values[15 + valuesStart] = (w12 >>> 42 | w13 << 22) & 0x3FFFFFFFFFFFFFL;
        values[16 + valuesStart] = (w13 >>> 32 | w14 << 32) & 0x3FFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w14 >>> 22 | w15 << 42) & 0x3FFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w15 >>> 12 | w16 << 52) & 0x3FFFFFFFFFFFFFL;
        values[19 + valuesStart] = w16 >>> 2 & 0x3FFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0x3FFFFFFFFFFFFFL;
        values[21 + valuesStart] = (w17 >>> 46 | w18 << 18) & 0x3FFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w18 >>> 36 | w19 << 28) & 0x3FFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w19 >>> 26 | w20 << 38) & 0x3FFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w20 >>> 16 | w21 << 48) & 0x3FFFFFFFFFFFFFL;
        values[25 + valuesStart] = w21 >>> 6 & 0x3FFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w21 >>> 60 | w22 << 4) & 0x3FFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w22 >>> 50 | w23 << 14) & 0x3FFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w23 >>> 40 | w24 << 24) & 0x3FFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w24 >>> 30 | w25 << 34) & 0x3FFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w25 >>> 20 | w26 << 44) & 0x3FFFFFFFFFFFFFL;
        values[31 + valuesStart] = w26 >>> 10;
        values[32 + valuesStart] = w27 & 0x3FFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w27 >>> 54 | w28 << 10) & 0x3FFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w28 >>> 44 | w29 << 20) & 0x3FFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w29 >>> 34 | w30 << 30) & 0x3FFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w30 >>> 24 | w31 << 40) & 0x3FFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w31 >>> 14 | w32 << 50) & 0x3FFFFFFFFFFFFFL;
        values[38 + valuesStart] = w32 >>> 4 & 0x3FFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w32 >>> 58 | w33 << 6) & 0x3FFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w33 >>> 48 | w34 << 16) & 0x3FFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w34 >>> 38 | w35 << 26) & 0x3FFFFFFFFFFFFFL;
        values[42 + valuesStart] = (w35 >>> 28 | w36 << 36) & 0x3FFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w36 >>> 18 | w37 << 46) & 0x3FFFFFFFFFFFFFL;
        values[44 + valuesStart] = w37 >>> 8 & 0x3FFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w37 >>> 62 | w38 << 2) & 0x3FFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w38 >>> 52 | w39 << 12) & 0x3FFFFFFFFFFFFFL;
        values[47 + valuesStart] = (w39 >>> 42 | w40 << 22) & 0x3FFFFFFFFFFFFFL;
        values[48 + valuesStart] = (w40 >>> 32 | w41 << 32) & 0x3FFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w41 >>> 22 | w42 << 42) & 0x3FFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w42 >>> 12 | w43 << 52) & 0x3FFFFFFFFFFFFFL;
        values[51 + valuesStart] = w43 >>> 2 & 0x3FFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w43 >>> 56 | w44 << 8) & 0x3FFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w44 >>> 46 | w45 << 18) & 0x3FFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w45 >>> 36 | w46 << 28) & 0x3FFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w46 >>> 26 | w47 << 38) & 0x3FFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w47 >>> 16 | w48 << 48) & 0x3FFFFFFFFFFFFFL;
        values[57 + valuesStart] = w48 >>> 6 & 0x3FFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w48 >>> 60 | w49 << 4) & 0x3FFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w49 >>> 50 | w50 << 14) & 0x3FFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w50 >>> 40 | w51 << 24) & 0x3FFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w51 >>> 30 | w52 << 34) & 0x3FFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w52 >>> 20 | w53 << 44) & 0x3FFFFFFFFFFFFFL;
        values[63 + valuesStart] = w53 >>> 10;
        return 432 + packedPtr;
    }

    /**
     * Unpacks 64 55-bit values using 440 bytes, touching 55 words.
     */
    private static long unpack55(long[] values, int valuesStart, long packedPtr) {
        // Access 55 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 55 | w1 << 9) & 0x7FFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 46 | w2 << 18) & 0x7FFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 37 | w3 << 27) & 0x7FFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 28 | w4 << 36) & 0x7FFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 19 | w5 << 45) & 0x7FFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w5 >>> 10 | w6 << 54) & 0x7FFFFFFFFFFFFFL;
        values[7 + valuesStart] = w6 >>> 1 & 0x7FFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w6 >>> 56 | w7 << 8) & 0x7FFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w7 >>> 47 | w8 << 17) & 0x7FFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w8 >>> 38 | w9 << 26) & 0x7FFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w9 >>> 29 | w10 << 35) & 0x7FFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w10 >>> 20 | w11 << 44) & 0x7FFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w11 >>> 11 | w12 << 53) & 0x7FFFFFFFFFFFFFL;
        values[14 + valuesStart] = w12 >>> 2 & 0x7FFFFFFFFFFFFFL;
        values[15 + valuesStart] = (w12 >>> 57 | w13 << 7) & 0x7FFFFFFFFFFFFFL;
        values[16 + valuesStart] = (w13 >>> 48 | w14 << 16) & 0x7FFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w14 >>> 39 | w15 << 25) & 0x7FFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w15 >>> 30 | w16 << 34) & 0x7FFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w16 >>> 21 | w17 << 43) & 0x7FFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w17 >>> 12 | w18 << 52) & 0x7FFFFFFFFFFFFFL;
        values[21 + valuesStart] = w18 >>> 3 & 0x7FFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w18 >>> 58 | w19 << 6) & 0x7FFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w19 >>> 49 | w20 << 15) & 0x7FFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w20 >>> 40 | w21 << 24) & 0x7FFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w21 >>> 31 | w22 << 33) & 0x7FFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w22 >>> 22 | w23 << 42) & 0x7FFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w23 >>> 13 | w24 << 51) & 0x7FFFFFFFFFFFFFL;
        values[28 + valuesStart] = w24 >>> 4 & 0x7FFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w24 >>> 59 | w25 << 5) & 0x7FFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w25 >>> 50 | w26 << 14) & 0x7FFFFFFFFFFFFFL;
        values[31 + valuesStart] = (w26 >>> 41 | w27 << 23) & 0x7FFFFFFFFFFFFFL;
        values[32 + valuesStart] = (w27 >>> 32 | w28 << 32) & 0x7FFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w28 >>> 23 | w29 << 41) & 0x7FFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w29 >>> 14 | w30 << 50) & 0x7FFFFFFFFFFFFFL;
        values[35 + valuesStart] = w30 >>> 5 & 0x7FFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w30 >>> 60 | w31 << 4) & 0x7FFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w31 >>> 51 | w32 << 13) & 0x7FFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w32 >>> 42 | w33 << 22) & 0x7FFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w33 >>> 33 | w34 << 31) & 0x7FFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w34 >>> 24 | w35 << 40) & 0x7FFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w35 >>> 15 | w36 << 49) & 0x7FFFFFFFFFFFFFL;
        values[42 + valuesStart] = w36 >>> 6 & 0x7FFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w36 >>> 61 | w37 << 3) & 0x7FFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w37 >>> 52 | w38 << 12) & 0x7FFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w38 >>> 43 | w39 << 21) & 0x7FFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w39 >>> 34 | w40 << 30) & 0x7FFFFFFFFFFFFFL;
        values[47 + valuesStart] = (w40 >>> 25 | w41 << 39) & 0x7FFFFFFFFFFFFFL;
        values[48 + valuesStart] = (w41 >>> 16 | w42 << 48) & 0x7FFFFFFFFFFFFFL;
        values[49 + valuesStart] = w42 >>> 7 & 0x7FFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w42 >>> 62 | w43 << 2) & 0x7FFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w43 >>> 53 | w44 << 11) & 0x7FFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w44 >>> 44 | w45 << 20) & 0x7FFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w45 >>> 35 | w46 << 29) & 0x7FFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w46 >>> 26 | w47 << 38) & 0x7FFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w47 >>> 17 | w48 << 47) & 0x7FFFFFFFFFFFFFL;
        values[56 + valuesStart] = w48 >>> 8 & 0x7FFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w48 >>> 63 | w49 << 1) & 0x7FFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w49 >>> 54 | w50 << 10) & 0x7FFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w50 >>> 45 | w51 << 19) & 0x7FFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w51 >>> 36 | w52 << 28) & 0x7FFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w52 >>> 27 | w53 << 37) & 0x7FFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w53 >>> 18 | w54 << 46) & 0x7FFFFFFFFFFFFFL;
        values[63 + valuesStart] = w54 >>> 9;
        return 440 + packedPtr;
    }

    /**
     * Unpacks 64 56-bit values using 448 bytes, touching 56 words.
     */
    private static long unpack56(long[] values, int valuesStart, long packedPtr) {
        // Access 56 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        long w55 = UnsafeUtil.getLong(440 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 56 | w1 << 8) & 0xFFFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 48 | w2 << 16) & 0xFFFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 40 | w3 << 24) & 0xFFFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 32 | w4 << 32) & 0xFFFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 24 | w5 << 40) & 0xFFFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w5 >>> 16 | w6 << 48) & 0xFFFFFFFFFFFFFFL;
        values[7 + valuesStart] = w6 >>> 8;
        values[8 + valuesStart] = w7 & 0xFFFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0xFFFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w8 >>> 48 | w9 << 16) & 0xFFFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w9 >>> 40 | w10 << 24) & 0xFFFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w10 >>> 32 | w11 << 32) & 0xFFFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w11 >>> 24 | w12 << 40) & 0xFFFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w12 >>> 16 | w13 << 48) & 0xFFFFFFFFFFFFFFL;
        values[15 + valuesStart] = w13 >>> 8;
        values[16 + valuesStart] = w14 & 0xFFFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w14 >>> 56 | w15 << 8) & 0xFFFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w15 >>> 48 | w16 << 16) & 0xFFFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w16 >>> 40 | w17 << 24) & 0xFFFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w17 >>> 32 | w18 << 32) & 0xFFFFFFFFFFFFFFL;
        values[21 + valuesStart] = (w18 >>> 24 | w19 << 40) & 0xFFFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w19 >>> 16 | w20 << 48) & 0xFFFFFFFFFFFFFFL;
        values[23 + valuesStart] = w20 >>> 8;
        values[24 + valuesStart] = w21 & 0xFFFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w21 >>> 56 | w22 << 8) & 0xFFFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w22 >>> 48 | w23 << 16) & 0xFFFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w23 >>> 40 | w24 << 24) & 0xFFFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w24 >>> 32 | w25 << 32) & 0xFFFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w25 >>> 24 | w26 << 40) & 0xFFFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w26 >>> 16 | w27 << 48) & 0xFFFFFFFFFFFFFFL;
        values[31 + valuesStart] = w27 >>> 8;
        values[32 + valuesStart] = w28 & 0xFFFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w28 >>> 56 | w29 << 8) & 0xFFFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w29 >>> 48 | w30 << 16) & 0xFFFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w30 >>> 40 | w31 << 24) & 0xFFFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w31 >>> 32 | w32 << 32) & 0xFFFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w32 >>> 24 | w33 << 40) & 0xFFFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w33 >>> 16 | w34 << 48) & 0xFFFFFFFFFFFFFFL;
        values[39 + valuesStart] = w34 >>> 8;
        values[40 + valuesStart] = w35 & 0xFFFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w35 >>> 56 | w36 << 8) & 0xFFFFFFFFFFFFFFL;
        values[42 + valuesStart] = (w36 >>> 48 | w37 << 16) & 0xFFFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w37 >>> 40 | w38 << 24) & 0xFFFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w38 >>> 32 | w39 << 32) & 0xFFFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w39 >>> 24 | w40 << 40) & 0xFFFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w40 >>> 16 | w41 << 48) & 0xFFFFFFFFFFFFFFL;
        values[47 + valuesStart] = w41 >>> 8;
        values[48 + valuesStart] = w42 & 0xFFFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w42 >>> 56 | w43 << 8) & 0xFFFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w43 >>> 48 | w44 << 16) & 0xFFFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w44 >>> 40 | w45 << 24) & 0xFFFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w45 >>> 32 | w46 << 32) & 0xFFFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w46 >>> 24 | w47 << 40) & 0xFFFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w47 >>> 16 | w48 << 48) & 0xFFFFFFFFFFFFFFL;
        values[55 + valuesStart] = w48 >>> 8;
        values[56 + valuesStart] = w49 & 0xFFFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w49 >>> 56 | w50 << 8) & 0xFFFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w50 >>> 48 | w51 << 16) & 0xFFFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w51 >>> 40 | w52 << 24) & 0xFFFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w52 >>> 32 | w53 << 32) & 0xFFFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w53 >>> 24 | w54 << 40) & 0xFFFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w54 >>> 16 | w55 << 48) & 0xFFFFFFFFFFFFFFL;
        values[63 + valuesStart] = w55 >>> 8;
        return 448 + packedPtr;
    }

    /**
     * Unpacks 64 57-bit values using 456 bytes, touching 57 words.
     */
    private static long unpack57(long[] values, int valuesStart, long packedPtr) {
        // Access 57 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        long w55 = UnsafeUtil.getLong(440 + packedPtr);
        long w56 = UnsafeUtil.getLong(448 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 57 | w1 << 7) & 0x1FFFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 50 | w2 << 14) & 0x1FFFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 43 | w3 << 21) & 0x1FFFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 36 | w4 << 28) & 0x1FFFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 29 | w5 << 35) & 0x1FFFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w5 >>> 22 | w6 << 42) & 0x1FFFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w6 >>> 15 | w7 << 49) & 0x1FFFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w7 >>> 8 | w8 << 56) & 0x1FFFFFFFFFFFFFFL;
        values[9 + valuesStart] = w8 >>> 1 & 0x1FFFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w8 >>> 58 | w9 << 6) & 0x1FFFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w9 >>> 51 | w10 << 13) & 0x1FFFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w10 >>> 44 | w11 << 20) & 0x1FFFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w11 >>> 37 | w12 << 27) & 0x1FFFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w12 >>> 30 | w13 << 34) & 0x1FFFFFFFFFFFFFFL;
        values[15 + valuesStart] = (w13 >>> 23 | w14 << 41) & 0x1FFFFFFFFFFFFFFL;
        values[16 + valuesStart] = (w14 >>> 16 | w15 << 48) & 0x1FFFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w15 >>> 9 | w16 << 55) & 0x1FFFFFFFFFFFFFFL;
        values[18 + valuesStart] = w16 >>> 2 & 0x1FFFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w16 >>> 59 | w17 << 5) & 0x1FFFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w17 >>> 52 | w18 << 12) & 0x1FFFFFFFFFFFFFFL;
        values[21 + valuesStart] = (w18 >>> 45 | w19 << 19) & 0x1FFFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w19 >>> 38 | w20 << 26) & 0x1FFFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w20 >>> 31 | w21 << 33) & 0x1FFFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w21 >>> 24 | w22 << 40) & 0x1FFFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w22 >>> 17 | w23 << 47) & 0x1FFFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w23 >>> 10 | w24 << 54) & 0x1FFFFFFFFFFFFFFL;
        values[27 + valuesStart] = w24 >>> 3 & 0x1FFFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w24 >>> 60 | w25 << 4) & 0x1FFFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w25 >>> 53 | w26 << 11) & 0x1FFFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w26 >>> 46 | w27 << 18) & 0x1FFFFFFFFFFFFFFL;
        values[31 + valuesStart] = (w27 >>> 39 | w28 << 25) & 0x1FFFFFFFFFFFFFFL;
        values[32 + valuesStart] = (w28 >>> 32 | w29 << 32) & 0x1FFFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w29 >>> 25 | w30 << 39) & 0x1FFFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w30 >>> 18 | w31 << 46) & 0x1FFFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w31 >>> 11 | w32 << 53) & 0x1FFFFFFFFFFFFFFL;
        values[36 + valuesStart] = w32 >>> 4 & 0x1FFFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w32 >>> 61 | w33 << 3) & 0x1FFFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w33 >>> 54 | w34 << 10) & 0x1FFFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w34 >>> 47 | w35 << 17) & 0x1FFFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w35 >>> 40 | w36 << 24) & 0x1FFFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w36 >>> 33 | w37 << 31) & 0x1FFFFFFFFFFFFFFL;
        values[42 + valuesStart] = (w37 >>> 26 | w38 << 38) & 0x1FFFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w38 >>> 19 | w39 << 45) & 0x1FFFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w39 >>> 12 | w40 << 52) & 0x1FFFFFFFFFFFFFFL;
        values[45 + valuesStart] = w40 >>> 5 & 0x1FFFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w40 >>> 62 | w41 << 2) & 0x1FFFFFFFFFFFFFFL;
        values[47 + valuesStart] = (w41 >>> 55 | w42 << 9) & 0x1FFFFFFFFFFFFFFL;
        values[48 + valuesStart] = (w42 >>> 48 | w43 << 16) & 0x1FFFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w43 >>> 41 | w44 << 23) & 0x1FFFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w44 >>> 34 | w45 << 30) & 0x1FFFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w45 >>> 27 | w46 << 37) & 0x1FFFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w46 >>> 20 | w47 << 44) & 0x1FFFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w47 >>> 13 | w48 << 51) & 0x1FFFFFFFFFFFFFFL;
        values[54 + valuesStart] = w48 >>> 6 & 0x1FFFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w48 >>> 63 | w49 << 1) & 0x1FFFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w49 >>> 56 | w50 << 8) & 0x1FFFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w50 >>> 49 | w51 << 15) & 0x1FFFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w51 >>> 42 | w52 << 22) & 0x1FFFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w52 >>> 35 | w53 << 29) & 0x1FFFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w53 >>> 28 | w54 << 36) & 0x1FFFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w54 >>> 21 | w55 << 43) & 0x1FFFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w55 >>> 14 | w56 << 50) & 0x1FFFFFFFFFFFFFFL;
        values[63 + valuesStart] = w56 >>> 7;
        return 456 + packedPtr;
    }

    /**
     * Unpacks 64 58-bit values using 464 bytes, touching 58 words.
     */
    private static long unpack58(long[] values, int valuesStart, long packedPtr) {
        // Access 58 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        long w55 = UnsafeUtil.getLong(440 + packedPtr);
        long w56 = UnsafeUtil.getLong(448 + packedPtr);
        long w57 = UnsafeUtil.getLong(456 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 58 | w1 << 6) & 0x3FFFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 52 | w2 << 12) & 0x3FFFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 46 | w3 << 18) & 0x3FFFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 40 | w4 << 24) & 0x3FFFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 34 | w5 << 30) & 0x3FFFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w5 >>> 28 | w6 << 36) & 0x3FFFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w6 >>> 22 | w7 << 42) & 0x3FFFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w7 >>> 16 | w8 << 48) & 0x3FFFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w8 >>> 10 | w9 << 54) & 0x3FFFFFFFFFFFFFFL;
        values[10 + valuesStart] = w9 >>> 4 & 0x3FFFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w9 >>> 62 | w10 << 2) & 0x3FFFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w10 >>> 56 | w11 << 8) & 0x3FFFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w11 >>> 50 | w12 << 14) & 0x3FFFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w12 >>> 44 | w13 << 20) & 0x3FFFFFFFFFFFFFFL;
        values[15 + valuesStart] = (w13 >>> 38 | w14 << 26) & 0x3FFFFFFFFFFFFFFL;
        values[16 + valuesStart] = (w14 >>> 32 | w15 << 32) & 0x3FFFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w15 >>> 26 | w16 << 38) & 0x3FFFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w16 >>> 20 | w17 << 44) & 0x3FFFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w17 >>> 14 | w18 << 50) & 0x3FFFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w18 >>> 8 | w19 << 56) & 0x3FFFFFFFFFFFFFFL;
        values[21 + valuesStart] = w19 >>> 2 & 0x3FFFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w19 >>> 60 | w20 << 4) & 0x3FFFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w20 >>> 54 | w21 << 10) & 0x3FFFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w21 >>> 48 | w22 << 16) & 0x3FFFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w22 >>> 42 | w23 << 22) & 0x3FFFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w23 >>> 36 | w24 << 28) & 0x3FFFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w24 >>> 30 | w25 << 34) & 0x3FFFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w25 >>> 24 | w26 << 40) & 0x3FFFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w26 >>> 18 | w27 << 46) & 0x3FFFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w27 >>> 12 | w28 << 52) & 0x3FFFFFFFFFFFFFFL;
        values[31 + valuesStart] = w28 >>> 6;
        values[32 + valuesStart] = w29 & 0x3FFFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w29 >>> 58 | w30 << 6) & 0x3FFFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w30 >>> 52 | w31 << 12) & 0x3FFFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w31 >>> 46 | w32 << 18) & 0x3FFFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w32 >>> 40 | w33 << 24) & 0x3FFFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w33 >>> 34 | w34 << 30) & 0x3FFFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w34 >>> 28 | w35 << 36) & 0x3FFFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w35 >>> 22 | w36 << 42) & 0x3FFFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w36 >>> 16 | w37 << 48) & 0x3FFFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w37 >>> 10 | w38 << 54) & 0x3FFFFFFFFFFFFFFL;
        values[42 + valuesStart] = w38 >>> 4 & 0x3FFFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w38 >>> 62 | w39 << 2) & 0x3FFFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w39 >>> 56 | w40 << 8) & 0x3FFFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w40 >>> 50 | w41 << 14) & 0x3FFFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w41 >>> 44 | w42 << 20) & 0x3FFFFFFFFFFFFFFL;
        values[47 + valuesStart] = (w42 >>> 38 | w43 << 26) & 0x3FFFFFFFFFFFFFFL;
        values[48 + valuesStart] = (w43 >>> 32 | w44 << 32) & 0x3FFFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w44 >>> 26 | w45 << 38) & 0x3FFFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w45 >>> 20 | w46 << 44) & 0x3FFFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w46 >>> 14 | w47 << 50) & 0x3FFFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w47 >>> 8 | w48 << 56) & 0x3FFFFFFFFFFFFFFL;
        values[53 + valuesStart] = w48 >>> 2 & 0x3FFFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w48 >>> 60 | w49 << 4) & 0x3FFFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w49 >>> 54 | w50 << 10) & 0x3FFFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w50 >>> 48 | w51 << 16) & 0x3FFFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w51 >>> 42 | w52 << 22) & 0x3FFFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w52 >>> 36 | w53 << 28) & 0x3FFFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w53 >>> 30 | w54 << 34) & 0x3FFFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w54 >>> 24 | w55 << 40) & 0x3FFFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w55 >>> 18 | w56 << 46) & 0x3FFFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w56 >>> 12 | w57 << 52) & 0x3FFFFFFFFFFFFFFL;
        values[63 + valuesStart] = w57 >>> 6;
        return 464 + packedPtr;
    }

    /**
     * Unpacks 64 59-bit values using 472 bytes, touching 59 words.
     */
    private static long unpack59(long[] values, int valuesStart, long packedPtr) {
        // Access 59 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        long w55 = UnsafeUtil.getLong(440 + packedPtr);
        long w56 = UnsafeUtil.getLong(448 + packedPtr);
        long w57 = UnsafeUtil.getLong(456 + packedPtr);
        long w58 = UnsafeUtil.getLong(464 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 59 | w1 << 5) & 0x7FFFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 54 | w2 << 10) & 0x7FFFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 49 | w3 << 15) & 0x7FFFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 44 | w4 << 20) & 0x7FFFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 39 | w5 << 25) & 0x7FFFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w5 >>> 34 | w6 << 30) & 0x7FFFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w6 >>> 29 | w7 << 35) & 0x7FFFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w7 >>> 24 | w8 << 40) & 0x7FFFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w8 >>> 19 | w9 << 45) & 0x7FFFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w9 >>> 14 | w10 << 50) & 0x7FFFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w10 >>> 9 | w11 << 55) & 0x7FFFFFFFFFFFFFFL;
        values[12 + valuesStart] = w11 >>> 4 & 0x7FFFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w11 >>> 63 | w12 << 1) & 0x7FFFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w12 >>> 58 | w13 << 6) & 0x7FFFFFFFFFFFFFFL;
        values[15 + valuesStart] = (w13 >>> 53 | w14 << 11) & 0x7FFFFFFFFFFFFFFL;
        values[16 + valuesStart] = (w14 >>> 48 | w15 << 16) & 0x7FFFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w15 >>> 43 | w16 << 21) & 0x7FFFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w16 >>> 38 | w17 << 26) & 0x7FFFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w17 >>> 33 | w18 << 31) & 0x7FFFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w18 >>> 28 | w19 << 36) & 0x7FFFFFFFFFFFFFFL;
        values[21 + valuesStart] = (w19 >>> 23 | w20 << 41) & 0x7FFFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w20 >>> 18 | w21 << 46) & 0x7FFFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w21 >>> 13 | w22 << 51) & 0x7FFFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w22 >>> 8 | w23 << 56) & 0x7FFFFFFFFFFFFFFL;
        values[25 + valuesStart] = w23 >>> 3 & 0x7FFFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w23 >>> 62 | w24 << 2) & 0x7FFFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w24 >>> 57 | w25 << 7) & 0x7FFFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w25 >>> 52 | w26 << 12) & 0x7FFFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w26 >>> 47 | w27 << 17) & 0x7FFFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w27 >>> 42 | w28 << 22) & 0x7FFFFFFFFFFFFFFL;
        values[31 + valuesStart] = (w28 >>> 37 | w29 << 27) & 0x7FFFFFFFFFFFFFFL;
        values[32 + valuesStart] = (w29 >>> 32 | w30 << 32) & 0x7FFFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w30 >>> 27 | w31 << 37) & 0x7FFFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w31 >>> 22 | w32 << 42) & 0x7FFFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w32 >>> 17 | w33 << 47) & 0x7FFFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w33 >>> 12 | w34 << 52) & 0x7FFFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w34 >>> 7 | w35 << 57) & 0x7FFFFFFFFFFFFFFL;
        values[38 + valuesStart] = w35 >>> 2 & 0x7FFFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w35 >>> 61 | w36 << 3) & 0x7FFFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w36 >>> 56 | w37 << 8) & 0x7FFFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w37 >>> 51 | w38 << 13) & 0x7FFFFFFFFFFFFFFL;
        values[42 + valuesStart] = (w38 >>> 46 | w39 << 18) & 0x7FFFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w39 >>> 41 | w40 << 23) & 0x7FFFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w40 >>> 36 | w41 << 28) & 0x7FFFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w41 >>> 31 | w42 << 33) & 0x7FFFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w42 >>> 26 | w43 << 38) & 0x7FFFFFFFFFFFFFFL;
        values[47 + valuesStart] = (w43 >>> 21 | w44 << 43) & 0x7FFFFFFFFFFFFFFL;
        values[48 + valuesStart] = (w44 >>> 16 | w45 << 48) & 0x7FFFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w45 >>> 11 | w46 << 53) & 0x7FFFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w46 >>> 6 | w47 << 58) & 0x7FFFFFFFFFFFFFFL;
        values[51 + valuesStart] = w47 >>> 1 & 0x7FFFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w47 >>> 60 | w48 << 4) & 0x7FFFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w48 >>> 55 | w49 << 9) & 0x7FFFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w49 >>> 50 | w50 << 14) & 0x7FFFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w50 >>> 45 | w51 << 19) & 0x7FFFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w51 >>> 40 | w52 << 24) & 0x7FFFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w52 >>> 35 | w53 << 29) & 0x7FFFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w53 >>> 30 | w54 << 34) & 0x7FFFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w54 >>> 25 | w55 << 39) & 0x7FFFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w55 >>> 20 | w56 << 44) & 0x7FFFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w56 >>> 15 | w57 << 49) & 0x7FFFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w57 >>> 10 | w58 << 54) & 0x7FFFFFFFFFFFFFFL;
        values[63 + valuesStart] = w58 >>> 5;
        return 472 + packedPtr;
    }

    /**
     * Unpacks 64 60-bit values using 480 bytes, touching 60 words.
     */
    private static long unpack60(long[] values, int valuesStart, long packedPtr) {
        // Access 60 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        long w55 = UnsafeUtil.getLong(440 + packedPtr);
        long w56 = UnsafeUtil.getLong(448 + packedPtr);
        long w57 = UnsafeUtil.getLong(456 + packedPtr);
        long w58 = UnsafeUtil.getLong(464 + packedPtr);
        long w59 = UnsafeUtil.getLong(472 + packedPtr);
        values[valuesStart] = w0 & 0xFFFFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 60 | w1 << 4) & 0xFFFFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 56 | w2 << 8) & 0xFFFFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 52 | w3 << 12) & 0xFFFFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 48 | w4 << 16) & 0xFFFFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 44 | w5 << 20) & 0xFFFFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w5 >>> 40 | w6 << 24) & 0xFFFFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w6 >>> 36 | w7 << 28) & 0xFFFFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w7 >>> 32 | w8 << 32) & 0xFFFFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w8 >>> 28 | w9 << 36) & 0xFFFFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w9 >>> 24 | w10 << 40) & 0xFFFFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w10 >>> 20 | w11 << 44) & 0xFFFFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w11 >>> 16 | w12 << 48) & 0xFFFFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w12 >>> 12 | w13 << 52) & 0xFFFFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w13 >>> 8 | w14 << 56) & 0xFFFFFFFFFFFFFFFL;
        values[15 + valuesStart] = w14 >>> 4;
        values[16 + valuesStart] = w15 & 0xFFFFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w15 >>> 60 | w16 << 4) & 0xFFFFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w16 >>> 56 | w17 << 8) & 0xFFFFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w17 >>> 52 | w18 << 12) & 0xFFFFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w18 >>> 48 | w19 << 16) & 0xFFFFFFFFFFFFFFFL;
        values[21 + valuesStart] = (w19 >>> 44 | w20 << 20) & 0xFFFFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w20 >>> 40 | w21 << 24) & 0xFFFFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w21 >>> 36 | w22 << 28) & 0xFFFFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w22 >>> 32 | w23 << 32) & 0xFFFFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w23 >>> 28 | w24 << 36) & 0xFFFFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w24 >>> 24 | w25 << 40) & 0xFFFFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w25 >>> 20 | w26 << 44) & 0xFFFFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w26 >>> 16 | w27 << 48) & 0xFFFFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w27 >>> 12 | w28 << 52) & 0xFFFFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w28 >>> 8 | w29 << 56) & 0xFFFFFFFFFFFFFFFL;
        values[31 + valuesStart] = w29 >>> 4;
        values[32 + valuesStart] = w30 & 0xFFFFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w30 >>> 60 | w31 << 4) & 0xFFFFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w31 >>> 56 | w32 << 8) & 0xFFFFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w32 >>> 52 | w33 << 12) & 0xFFFFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w33 >>> 48 | w34 << 16) & 0xFFFFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w34 >>> 44 | w35 << 20) & 0xFFFFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w35 >>> 40 | w36 << 24) & 0xFFFFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w36 >>> 36 | w37 << 28) & 0xFFFFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w37 >>> 32 | w38 << 32) & 0xFFFFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w38 >>> 28 | w39 << 36) & 0xFFFFFFFFFFFFFFFL;
        values[42 + valuesStart] = (w39 >>> 24 | w40 << 40) & 0xFFFFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w40 >>> 20 | w41 << 44) & 0xFFFFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w41 >>> 16 | w42 << 48) & 0xFFFFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w42 >>> 12 | w43 << 52) & 0xFFFFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w43 >>> 8 | w44 << 56) & 0xFFFFFFFFFFFFFFFL;
        values[47 + valuesStart] = w44 >>> 4;
        values[48 + valuesStart] = w45 & 0xFFFFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w45 >>> 60 | w46 << 4) & 0xFFFFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w46 >>> 56 | w47 << 8) & 0xFFFFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w47 >>> 52 | w48 << 12) & 0xFFFFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w48 >>> 48 | w49 << 16) & 0xFFFFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w49 >>> 44 | w50 << 20) & 0xFFFFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w50 >>> 40 | w51 << 24) & 0xFFFFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w51 >>> 36 | w52 << 28) & 0xFFFFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w52 >>> 32 | w53 << 32) & 0xFFFFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w53 >>> 28 | w54 << 36) & 0xFFFFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w54 >>> 24 | w55 << 40) & 0xFFFFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w55 >>> 20 | w56 << 44) & 0xFFFFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w56 >>> 16 | w57 << 48) & 0xFFFFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w57 >>> 12 | w58 << 52) & 0xFFFFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w58 >>> 8 | w59 << 56) & 0xFFFFFFFFFFFFFFFL;
        values[63 + valuesStart] = w59 >>> 4;
        return 480 + packedPtr;
    }

    /**
     * Unpacks 64 61-bit values using 488 bytes, touching 61 words.
     */
    private static long unpack61(long[] values, int valuesStart, long packedPtr) {
        // Access 61 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        long w55 = UnsafeUtil.getLong(440 + packedPtr);
        long w56 = UnsafeUtil.getLong(448 + packedPtr);
        long w57 = UnsafeUtil.getLong(456 + packedPtr);
        long w58 = UnsafeUtil.getLong(464 + packedPtr);
        long w59 = UnsafeUtil.getLong(472 + packedPtr);
        long w60 = UnsafeUtil.getLong(480 + packedPtr);
        values[valuesStart] = w0 & 0x1FFFFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 61 | w1 << 3) & 0x1FFFFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 58 | w2 << 6) & 0x1FFFFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 55 | w3 << 9) & 0x1FFFFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 52 | w4 << 12) & 0x1FFFFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 49 | w5 << 15) & 0x1FFFFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w5 >>> 46 | w6 << 18) & 0x1FFFFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w6 >>> 43 | w7 << 21) & 0x1FFFFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w7 >>> 40 | w8 << 24) & 0x1FFFFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w8 >>> 37 | w9 << 27) & 0x1FFFFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w9 >>> 34 | w10 << 30) & 0x1FFFFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w10 >>> 31 | w11 << 33) & 0x1FFFFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w11 >>> 28 | w12 << 36) & 0x1FFFFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w12 >>> 25 | w13 << 39) & 0x1FFFFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w13 >>> 22 | w14 << 42) & 0x1FFFFFFFFFFFFFFFL;
        values[15 + valuesStart] = (w14 >>> 19 | w15 << 45) & 0x1FFFFFFFFFFFFFFFL;
        values[16 + valuesStart] = (w15 >>> 16 | w16 << 48) & 0x1FFFFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w16 >>> 13 | w17 << 51) & 0x1FFFFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w17 >>> 10 | w18 << 54) & 0x1FFFFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w18 >>> 7 | w19 << 57) & 0x1FFFFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w19 >>> 4 | w20 << 60) & 0x1FFFFFFFFFFFFFFFL;
        values[21 + valuesStart] = w20 >>> 1 & 0x1FFFFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w20 >>> 62 | w21 << 2) & 0x1FFFFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w21 >>> 59 | w22 << 5) & 0x1FFFFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w22 >>> 56 | w23 << 8) & 0x1FFFFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w23 >>> 53 | w24 << 11) & 0x1FFFFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w24 >>> 50 | w25 << 14) & 0x1FFFFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w25 >>> 47 | w26 << 17) & 0x1FFFFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w26 >>> 44 | w27 << 20) & 0x1FFFFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w27 >>> 41 | w28 << 23) & 0x1FFFFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w28 >>> 38 | w29 << 26) & 0x1FFFFFFFFFFFFFFFL;
        values[31 + valuesStart] = (w29 >>> 35 | w30 << 29) & 0x1FFFFFFFFFFFFFFFL;
        values[32 + valuesStart] = (w30 >>> 32 | w31 << 32) & 0x1FFFFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w31 >>> 29 | w32 << 35) & 0x1FFFFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w32 >>> 26 | w33 << 38) & 0x1FFFFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w33 >>> 23 | w34 << 41) & 0x1FFFFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w34 >>> 20 | w35 << 44) & 0x1FFFFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w35 >>> 17 | w36 << 47) & 0x1FFFFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w36 >>> 14 | w37 << 50) & 0x1FFFFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w37 >>> 11 | w38 << 53) & 0x1FFFFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w38 >>> 8 | w39 << 56) & 0x1FFFFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w39 >>> 5 | w40 << 59) & 0x1FFFFFFFFFFFFFFFL;
        values[42 + valuesStart] = w40 >>> 2 & 0x1FFFFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w40 >>> 63 | w41 << 1) & 0x1FFFFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w41 >>> 60 | w42 << 4) & 0x1FFFFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w42 >>> 57 | w43 << 7) & 0x1FFFFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w43 >>> 54 | w44 << 10) & 0x1FFFFFFFFFFFFFFFL;
        values[47 + valuesStart] = (w44 >>> 51 | w45 << 13) & 0x1FFFFFFFFFFFFFFFL;
        values[48 + valuesStart] = (w45 >>> 48 | w46 << 16) & 0x1FFFFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w46 >>> 45 | w47 << 19) & 0x1FFFFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w47 >>> 42 | w48 << 22) & 0x1FFFFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w48 >>> 39 | w49 << 25) & 0x1FFFFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w49 >>> 36 | w50 << 28) & 0x1FFFFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w50 >>> 33 | w51 << 31) & 0x1FFFFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w51 >>> 30 | w52 << 34) & 0x1FFFFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w52 >>> 27 | w53 << 37) & 0x1FFFFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w53 >>> 24 | w54 << 40) & 0x1FFFFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w54 >>> 21 | w55 << 43) & 0x1FFFFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w55 >>> 18 | w56 << 46) & 0x1FFFFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w56 >>> 15 | w57 << 49) & 0x1FFFFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w57 >>> 12 | w58 << 52) & 0x1FFFFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w58 >>> 9 | w59 << 55) & 0x1FFFFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w59 >>> 6 | w60 << 58) & 0x1FFFFFFFFFFFFFFFL;
        values[63 + valuesStart] = w60 >>> 3;
        return 488 + packedPtr;
    }

    /**
     * Unpacks 64 62-bit values using 496 bytes, touching 62 words.
     */
    private static long unpack62(long[] values, int valuesStart, long packedPtr) {
        // Access 62 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        long w55 = UnsafeUtil.getLong(440 + packedPtr);
        long w56 = UnsafeUtil.getLong(448 + packedPtr);
        long w57 = UnsafeUtil.getLong(456 + packedPtr);
        long w58 = UnsafeUtil.getLong(464 + packedPtr);
        long w59 = UnsafeUtil.getLong(472 + packedPtr);
        long w60 = UnsafeUtil.getLong(480 + packedPtr);
        long w61 = UnsafeUtil.getLong(488 + packedPtr);
        values[valuesStart] = w0 & 0x3FFFFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 62 | w1 << 2) & 0x3FFFFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 60 | w2 << 4) & 0x3FFFFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 58 | w3 << 6) & 0x3FFFFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 56 | w4 << 8) & 0x3FFFFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 54 | w5 << 10) & 0x3FFFFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w5 >>> 52 | w6 << 12) & 0x3FFFFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w6 >>> 50 | w7 << 14) & 0x3FFFFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w7 >>> 48 | w8 << 16) & 0x3FFFFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w8 >>> 46 | w9 << 18) & 0x3FFFFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w9 >>> 44 | w10 << 20) & 0x3FFFFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w10 >>> 42 | w11 << 22) & 0x3FFFFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w11 >>> 40 | w12 << 24) & 0x3FFFFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w12 >>> 38 | w13 << 26) & 0x3FFFFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w13 >>> 36 | w14 << 28) & 0x3FFFFFFFFFFFFFFFL;
        values[15 + valuesStart] = (w14 >>> 34 | w15 << 30) & 0x3FFFFFFFFFFFFFFFL;
        values[16 + valuesStart] = (w15 >>> 32 | w16 << 32) & 0x3FFFFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w16 >>> 30 | w17 << 34) & 0x3FFFFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w17 >>> 28 | w18 << 36) & 0x3FFFFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w18 >>> 26 | w19 << 38) & 0x3FFFFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w19 >>> 24 | w20 << 40) & 0x3FFFFFFFFFFFFFFFL;
        values[21 + valuesStart] = (w20 >>> 22 | w21 << 42) & 0x3FFFFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w21 >>> 20 | w22 << 44) & 0x3FFFFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w22 >>> 18 | w23 << 46) & 0x3FFFFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w23 >>> 16 | w24 << 48) & 0x3FFFFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w24 >>> 14 | w25 << 50) & 0x3FFFFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w25 >>> 12 | w26 << 52) & 0x3FFFFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w26 >>> 10 | w27 << 54) & 0x3FFFFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w27 >>> 8 | w28 << 56) & 0x3FFFFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w28 >>> 6 | w29 << 58) & 0x3FFFFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w29 >>> 4 | w30 << 60) & 0x3FFFFFFFFFFFFFFFL;
        values[31 + valuesStart] = w30 >>> 2;
        values[32 + valuesStart] = w31 & 0x3FFFFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w31 >>> 62 | w32 << 2) & 0x3FFFFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w32 >>> 60 | w33 << 4) & 0x3FFFFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w33 >>> 58 | w34 << 6) & 0x3FFFFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w34 >>> 56 | w35 << 8) & 0x3FFFFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w35 >>> 54 | w36 << 10) & 0x3FFFFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w36 >>> 52 | w37 << 12) & 0x3FFFFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w37 >>> 50 | w38 << 14) & 0x3FFFFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w38 >>> 48 | w39 << 16) & 0x3FFFFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w39 >>> 46 | w40 << 18) & 0x3FFFFFFFFFFFFFFFL;
        values[42 + valuesStart] = (w40 >>> 44 | w41 << 20) & 0x3FFFFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w41 >>> 42 | w42 << 22) & 0x3FFFFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w42 >>> 40 | w43 << 24) & 0x3FFFFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w43 >>> 38 | w44 << 26) & 0x3FFFFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w44 >>> 36 | w45 << 28) & 0x3FFFFFFFFFFFFFFFL;
        values[47 + valuesStart] = (w45 >>> 34 | w46 << 30) & 0x3FFFFFFFFFFFFFFFL;
        values[48 + valuesStart] = (w46 >>> 32 | w47 << 32) & 0x3FFFFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w47 >>> 30 | w48 << 34) & 0x3FFFFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w48 >>> 28 | w49 << 36) & 0x3FFFFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w49 >>> 26 | w50 << 38) & 0x3FFFFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w50 >>> 24 | w51 << 40) & 0x3FFFFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w51 >>> 22 | w52 << 42) & 0x3FFFFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w52 >>> 20 | w53 << 44) & 0x3FFFFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w53 >>> 18 | w54 << 46) & 0x3FFFFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w54 >>> 16 | w55 << 48) & 0x3FFFFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w55 >>> 14 | w56 << 50) & 0x3FFFFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w56 >>> 12 | w57 << 52) & 0x3FFFFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w57 >>> 10 | w58 << 54) & 0x3FFFFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w58 >>> 8 | w59 << 56) & 0x3FFFFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w59 >>> 6 | w60 << 58) & 0x3FFFFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w60 >>> 4 | w61 << 60) & 0x3FFFFFFFFFFFFFFFL;
        values[63 + valuesStart] = w61 >>> 2;
        return 496 + packedPtr;
    }

    /**
     * Unpacks 64 63-bit values using 504 bytes, touching 63 words.
     */
    private static long unpack63(long[] values, int valuesStart, long packedPtr) {
        // Access 63 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        long w55 = UnsafeUtil.getLong(440 + packedPtr);
        long w56 = UnsafeUtil.getLong(448 + packedPtr);
        long w57 = UnsafeUtil.getLong(456 + packedPtr);
        long w58 = UnsafeUtil.getLong(464 + packedPtr);
        long w59 = UnsafeUtil.getLong(472 + packedPtr);
        long w60 = UnsafeUtil.getLong(480 + packedPtr);
        long w61 = UnsafeUtil.getLong(488 + packedPtr);
        long w62 = UnsafeUtil.getLong(496 + packedPtr);
        values[valuesStart] = w0 & 0x7FFFFFFFFFFFFFFFL;
        values[1 + valuesStart] = (w0 >>> 63 | w1 << 1) & 0x7FFFFFFFFFFFFFFFL;
        values[2 + valuesStart] = (w1 >>> 62 | w2 << 2) & 0x7FFFFFFFFFFFFFFFL;
        values[3 + valuesStart] = (w2 >>> 61 | w3 << 3) & 0x7FFFFFFFFFFFFFFFL;
        values[4 + valuesStart] = (w3 >>> 60 | w4 << 4) & 0x7FFFFFFFFFFFFFFFL;
        values[5 + valuesStart] = (w4 >>> 59 | w5 << 5) & 0x7FFFFFFFFFFFFFFFL;
        values[6 + valuesStart] = (w5 >>> 58 | w6 << 6) & 0x7FFFFFFFFFFFFFFFL;
        values[7 + valuesStart] = (w6 >>> 57 | w7 << 7) & 0x7FFFFFFFFFFFFFFFL;
        values[8 + valuesStart] = (w7 >>> 56 | w8 << 8) & 0x7FFFFFFFFFFFFFFFL;
        values[9 + valuesStart] = (w8 >>> 55 | w9 << 9) & 0x7FFFFFFFFFFFFFFFL;
        values[10 + valuesStart] = (w9 >>> 54 | w10 << 10) & 0x7FFFFFFFFFFFFFFFL;
        values[11 + valuesStart] = (w10 >>> 53 | w11 << 11) & 0x7FFFFFFFFFFFFFFFL;
        values[12 + valuesStart] = (w11 >>> 52 | w12 << 12) & 0x7FFFFFFFFFFFFFFFL;
        values[13 + valuesStart] = (w12 >>> 51 | w13 << 13) & 0x7FFFFFFFFFFFFFFFL;
        values[14 + valuesStart] = (w13 >>> 50 | w14 << 14) & 0x7FFFFFFFFFFFFFFFL;
        values[15 + valuesStart] = (w14 >>> 49 | w15 << 15) & 0x7FFFFFFFFFFFFFFFL;
        values[16 + valuesStart] = (w15 >>> 48 | w16 << 16) & 0x7FFFFFFFFFFFFFFFL;
        values[17 + valuesStart] = (w16 >>> 47 | w17 << 17) & 0x7FFFFFFFFFFFFFFFL;
        values[18 + valuesStart] = (w17 >>> 46 | w18 << 18) & 0x7FFFFFFFFFFFFFFFL;
        values[19 + valuesStart] = (w18 >>> 45 | w19 << 19) & 0x7FFFFFFFFFFFFFFFL;
        values[20 + valuesStart] = (w19 >>> 44 | w20 << 20) & 0x7FFFFFFFFFFFFFFFL;
        values[21 + valuesStart] = (w20 >>> 43 | w21 << 21) & 0x7FFFFFFFFFFFFFFFL;
        values[22 + valuesStart] = (w21 >>> 42 | w22 << 22) & 0x7FFFFFFFFFFFFFFFL;
        values[23 + valuesStart] = (w22 >>> 41 | w23 << 23) & 0x7FFFFFFFFFFFFFFFL;
        values[24 + valuesStart] = (w23 >>> 40 | w24 << 24) & 0x7FFFFFFFFFFFFFFFL;
        values[25 + valuesStart] = (w24 >>> 39 | w25 << 25) & 0x7FFFFFFFFFFFFFFFL;
        values[26 + valuesStart] = (w25 >>> 38 | w26 << 26) & 0x7FFFFFFFFFFFFFFFL;
        values[27 + valuesStart] = (w26 >>> 37 | w27 << 27) & 0x7FFFFFFFFFFFFFFFL;
        values[28 + valuesStart] = (w27 >>> 36 | w28 << 28) & 0x7FFFFFFFFFFFFFFFL;
        values[29 + valuesStart] = (w28 >>> 35 | w29 << 29) & 0x7FFFFFFFFFFFFFFFL;
        values[30 + valuesStart] = (w29 >>> 34 | w30 << 30) & 0x7FFFFFFFFFFFFFFFL;
        values[31 + valuesStart] = (w30 >>> 33 | w31 << 31) & 0x7FFFFFFFFFFFFFFFL;
        values[32 + valuesStart] = (w31 >>> 32 | w32 << 32) & 0x7FFFFFFFFFFFFFFFL;
        values[33 + valuesStart] = (w32 >>> 31 | w33 << 33) & 0x7FFFFFFFFFFFFFFFL;
        values[34 + valuesStart] = (w33 >>> 30 | w34 << 34) & 0x7FFFFFFFFFFFFFFFL;
        values[35 + valuesStart] = (w34 >>> 29 | w35 << 35) & 0x7FFFFFFFFFFFFFFFL;
        values[36 + valuesStart] = (w35 >>> 28 | w36 << 36) & 0x7FFFFFFFFFFFFFFFL;
        values[37 + valuesStart] = (w36 >>> 27 | w37 << 37) & 0x7FFFFFFFFFFFFFFFL;
        values[38 + valuesStart] = (w37 >>> 26 | w38 << 38) & 0x7FFFFFFFFFFFFFFFL;
        values[39 + valuesStart] = (w38 >>> 25 | w39 << 39) & 0x7FFFFFFFFFFFFFFFL;
        values[40 + valuesStart] = (w39 >>> 24 | w40 << 40) & 0x7FFFFFFFFFFFFFFFL;
        values[41 + valuesStart] = (w40 >>> 23 | w41 << 41) & 0x7FFFFFFFFFFFFFFFL;
        values[42 + valuesStart] = (w41 >>> 22 | w42 << 42) & 0x7FFFFFFFFFFFFFFFL;
        values[43 + valuesStart] = (w42 >>> 21 | w43 << 43) & 0x7FFFFFFFFFFFFFFFL;
        values[44 + valuesStart] = (w43 >>> 20 | w44 << 44) & 0x7FFFFFFFFFFFFFFFL;
        values[45 + valuesStart] = (w44 >>> 19 | w45 << 45) & 0x7FFFFFFFFFFFFFFFL;
        values[46 + valuesStart] = (w45 >>> 18 | w46 << 46) & 0x7FFFFFFFFFFFFFFFL;
        values[47 + valuesStart] = (w46 >>> 17 | w47 << 47) & 0x7FFFFFFFFFFFFFFFL;
        values[48 + valuesStart] = (w47 >>> 16 | w48 << 48) & 0x7FFFFFFFFFFFFFFFL;
        values[49 + valuesStart] = (w48 >>> 15 | w49 << 49) & 0x7FFFFFFFFFFFFFFFL;
        values[50 + valuesStart] = (w49 >>> 14 | w50 << 50) & 0x7FFFFFFFFFFFFFFFL;
        values[51 + valuesStart] = (w50 >>> 13 | w51 << 51) & 0x7FFFFFFFFFFFFFFFL;
        values[52 + valuesStart] = (w51 >>> 12 | w52 << 52) & 0x7FFFFFFFFFFFFFFFL;
        values[53 + valuesStart] = (w52 >>> 11 | w53 << 53) & 0x7FFFFFFFFFFFFFFFL;
        values[54 + valuesStart] = (w53 >>> 10 | w54 << 54) & 0x7FFFFFFFFFFFFFFFL;
        values[55 + valuesStart] = (w54 >>> 9 | w55 << 55) & 0x7FFFFFFFFFFFFFFFL;
        values[56 + valuesStart] = (w55 >>> 8 | w56 << 56) & 0x7FFFFFFFFFFFFFFFL;
        values[57 + valuesStart] = (w56 >>> 7 | w57 << 57) & 0x7FFFFFFFFFFFFFFFL;
        values[58 + valuesStart] = (w57 >>> 6 | w58 << 58) & 0x7FFFFFFFFFFFFFFFL;
        values[59 + valuesStart] = (w58 >>> 5 | w59 << 59) & 0x7FFFFFFFFFFFFFFFL;
        values[60 + valuesStart] = (w59 >>> 4 | w60 << 60) & 0x7FFFFFFFFFFFFFFFL;
        values[61 + valuesStart] = (w60 >>> 3 | w61 << 61) & 0x7FFFFFFFFFFFFFFFL;
        values[62 + valuesStart] = (w61 >>> 2 | w62 << 62) & 0x7FFFFFFFFFFFFFFFL;
        values[63 + valuesStart] = w62 >>> 1;
        return 504 + packedPtr;
    }

    /**
     * Unpacks 64 64-bit values using 512 bytes, touching 64 words.
     */
    private static long unpack64(long[] values, int valuesStart, long packedPtr) {
        // Access 64 words
        long w0 = UnsafeUtil.getLong(packedPtr);
        long w1 = UnsafeUtil.getLong(8 + packedPtr);
        long w2 = UnsafeUtil.getLong(16 + packedPtr);
        long w3 = UnsafeUtil.getLong(24 + packedPtr);
        long w4 = UnsafeUtil.getLong(32 + packedPtr);
        long w5 = UnsafeUtil.getLong(40 + packedPtr);
        long w6 = UnsafeUtil.getLong(48 + packedPtr);
        long w7 = UnsafeUtil.getLong(56 + packedPtr);
        long w8 = UnsafeUtil.getLong(64 + packedPtr);
        long w9 = UnsafeUtil.getLong(72 + packedPtr);
        long w10 = UnsafeUtil.getLong(80 + packedPtr);
        long w11 = UnsafeUtil.getLong(88 + packedPtr);
        long w12 = UnsafeUtil.getLong(96 + packedPtr);
        long w13 = UnsafeUtil.getLong(104 + packedPtr);
        long w14 = UnsafeUtil.getLong(112 + packedPtr);
        long w15 = UnsafeUtil.getLong(120 + packedPtr);
        long w16 = UnsafeUtil.getLong(128 + packedPtr);
        long w17 = UnsafeUtil.getLong(136 + packedPtr);
        long w18 = UnsafeUtil.getLong(144 + packedPtr);
        long w19 = UnsafeUtil.getLong(152 + packedPtr);
        long w20 = UnsafeUtil.getLong(160 + packedPtr);
        long w21 = UnsafeUtil.getLong(168 + packedPtr);
        long w22 = UnsafeUtil.getLong(176 + packedPtr);
        long w23 = UnsafeUtil.getLong(184 + packedPtr);
        long w24 = UnsafeUtil.getLong(192 + packedPtr);
        long w25 = UnsafeUtil.getLong(200 + packedPtr);
        long w26 = UnsafeUtil.getLong(208 + packedPtr);
        long w27 = UnsafeUtil.getLong(216 + packedPtr);
        long w28 = UnsafeUtil.getLong(224 + packedPtr);
        long w29 = UnsafeUtil.getLong(232 + packedPtr);
        long w30 = UnsafeUtil.getLong(240 + packedPtr);
        long w31 = UnsafeUtil.getLong(248 + packedPtr);
        long w32 = UnsafeUtil.getLong(256 + packedPtr);
        long w33 = UnsafeUtil.getLong(264 + packedPtr);
        long w34 = UnsafeUtil.getLong(272 + packedPtr);
        long w35 = UnsafeUtil.getLong(280 + packedPtr);
        long w36 = UnsafeUtil.getLong(288 + packedPtr);
        long w37 = UnsafeUtil.getLong(296 + packedPtr);
        long w38 = UnsafeUtil.getLong(304 + packedPtr);
        long w39 = UnsafeUtil.getLong(312 + packedPtr);
        long w40 = UnsafeUtil.getLong(320 + packedPtr);
        long w41 = UnsafeUtil.getLong(328 + packedPtr);
        long w42 = UnsafeUtil.getLong(336 + packedPtr);
        long w43 = UnsafeUtil.getLong(344 + packedPtr);
        long w44 = UnsafeUtil.getLong(352 + packedPtr);
        long w45 = UnsafeUtil.getLong(360 + packedPtr);
        long w46 = UnsafeUtil.getLong(368 + packedPtr);
        long w47 = UnsafeUtil.getLong(376 + packedPtr);
        long w48 = UnsafeUtil.getLong(384 + packedPtr);
        long w49 = UnsafeUtil.getLong(392 + packedPtr);
        long w50 = UnsafeUtil.getLong(400 + packedPtr);
        long w51 = UnsafeUtil.getLong(408 + packedPtr);
        long w52 = UnsafeUtil.getLong(416 + packedPtr);
        long w53 = UnsafeUtil.getLong(424 + packedPtr);
        long w54 = UnsafeUtil.getLong(432 + packedPtr);
        long w55 = UnsafeUtil.getLong(440 + packedPtr);
        long w56 = UnsafeUtil.getLong(448 + packedPtr);
        long w57 = UnsafeUtil.getLong(456 + packedPtr);
        long w58 = UnsafeUtil.getLong(464 + packedPtr);
        long w59 = UnsafeUtil.getLong(472 + packedPtr);
        long w60 = UnsafeUtil.getLong(480 + packedPtr);
        long w61 = UnsafeUtil.getLong(488 + packedPtr);
        long w62 = UnsafeUtil.getLong(496 + packedPtr);
        long w63 = UnsafeUtil.getLong(504 + packedPtr);
        values[valuesStart] = w0;
        values[1 + valuesStart] = w1;
        values[2 + valuesStart] = w2;
        values[3 + valuesStart] = w3;
        values[4 + valuesStart] = w4;
        values[5 + valuesStart] = w5;
        values[6 + valuesStart] = w6;
        values[7 + valuesStart] = w7;
        values[8 + valuesStart] = w8;
        values[9 + valuesStart] = w9;
        values[10 + valuesStart] = w10;
        values[11 + valuesStart] = w11;
        values[12 + valuesStart] = w12;
        values[13 + valuesStart] = w13;
        values[14 + valuesStart] = w14;
        values[15 + valuesStart] = w15;
        values[16 + valuesStart] = w16;
        values[17 + valuesStart] = w17;
        values[18 + valuesStart] = w18;
        values[19 + valuesStart] = w19;
        values[20 + valuesStart] = w20;
        values[21 + valuesStart] = w21;
        values[22 + valuesStart] = w22;
        values[23 + valuesStart] = w23;
        values[24 + valuesStart] = w24;
        values[25 + valuesStart] = w25;
        values[26 + valuesStart] = w26;
        values[27 + valuesStart] = w27;
        values[28 + valuesStart] = w28;
        values[29 + valuesStart] = w29;
        values[30 + valuesStart] = w30;
        values[31 + valuesStart] = w31;
        values[32 + valuesStart] = w32;
        values[33 + valuesStart] = w33;
        values[34 + valuesStart] = w34;
        values[35 + valuesStart] = w35;
        values[36 + valuesStart] = w36;
        values[37 + valuesStart] = w37;
        values[38 + valuesStart] = w38;
        values[39 + valuesStart] = w39;
        values[40 + valuesStart] = w40;
        values[41 + valuesStart] = w41;
        values[42 + valuesStart] = w42;
        values[43 + valuesStart] = w43;
        values[44 + valuesStart] = w44;
        values[45 + valuesStart] = w45;
        values[46 + valuesStart] = w46;
        values[47 + valuesStart] = w47;
        values[48 + valuesStart] = w48;
        values[49 + valuesStart] = w49;
        values[50 + valuesStart] = w50;
        values[51 + valuesStart] = w51;
        values[52 + valuesStart] = w52;
        values[53 + valuesStart] = w53;
        values[54 + valuesStart] = w54;
        values[55 + valuesStart] = w55;
        values[56 + valuesStart] = w56;
        values[57 + valuesStart] = w57;
        values[58 + valuesStart] = w58;
        values[59 + valuesStart] = w59;
        values[60 + valuesStart] = w60;
        values[61 + valuesStart] = w61;
        values[62 + valuesStart] = w62;
        values[63 + valuesStart] = w63;
        return 512 + packedPtr;
    }

    /**
     * Unpacks `valuesLength` 0-bit values.
     */
    private static long unpackLoop0(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        java.util.Arrays.fill(values, valuesStart, valuesStart + valuesLength, 0x0L);
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 1-bit values.
     */
    private static long unpackLoop1(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1L;
            values[offset + 1 + valuesStart] = word >>> shift + 1 & 0x1L;
            values[offset + 2 + valuesStart] = word >>> shift + 2 & 0x1L;
            values[offset + 3 + valuesStart] = word >>> shift + 3 & 0x1L;
            values[offset + 4 + valuesStart] = word >>> shift + 4 & 0x1L;
            values[offset + 5 + valuesStart] = word >>> shift + 5 & 0x1L;
            values[offset + 6 + valuesStart] = word >>> shift + 6 & 0x1L;
            values[offset + 7 + valuesStart] = word >>> shift + 7 & 0x1L;
            values[offset + 8 + valuesStart] = word >>> shift + 8 & 0x1L;
            values[offset + 9 + valuesStart] = word >>> shift + 9 & 0x1L;
            values[offset + 10 + valuesStart] = word >>> shift + 10 & 0x1L;
            values[offset + 11 + valuesStart] = word >>> shift + 11 & 0x1L;
            values[offset + 12 + valuesStart] = word >>> shift + 12 & 0x1L;
            values[offset + 13 + valuesStart] = word >>> shift + 13 & 0x1L;
            values[offset + 14 + valuesStart] = word >>> shift + 14 & 0x1L;
            values[offset + 15 + valuesStart] = word >>> shift + 15 & 0x1L;
            values[offset + 16 + valuesStart] = word >>> shift + 16 & 0x1L;
            values[offset + 17 + valuesStart] = word >>> shift + 17 & 0x1L;
            values[offset + 18 + valuesStart] = word >>> shift + 18 & 0x1L;
            values[offset + 19 + valuesStart] = word >>> shift + 19 & 0x1L;
            values[offset + 20 + valuesStart] = word >>> shift + 20 & 0x1L;
            values[offset + 21 + valuesStart] = word >>> shift + 21 & 0x1L;
            values[offset + 22 + valuesStart] = word >>> shift + 22 & 0x1L;
            values[offset + 23 + valuesStart] = word >>> shift + 23 & 0x1L;
            values[offset + 24 + valuesStart] = word >>> shift + 24 & 0x1L;
            values[offset + 25 + valuesStart] = word >>> shift + 25 & 0x1L;
            values[offset + 26 + valuesStart] = word >>> shift + 26 & 0x1L;
            values[offset + 27 + valuesStart] = word >>> shift + 27 & 0x1L;
            values[offset + 28 + valuesStart] = word >>> shift + 28 & 0x1L;
            values[offset + 29 + valuesStart] = word >>> shift + 29 & 0x1L;
            values[offset + 30 + valuesStart] = word >>> shift + 30 & 0x1L;
            values[offset + 31 + valuesStart] = word >>> shift + 31 & 0x1L;
            values[offset + 32 + valuesStart] = word >>> shift + 32 & 0x1L;
            values[offset + 33 + valuesStart] = word >>> shift + 33 & 0x1L;
            values[offset + 34 + valuesStart] = word >>> shift + 34 & 0x1L;
            values[offset + 35 + valuesStart] = word >>> shift + 35 & 0x1L;
            values[offset + 36 + valuesStart] = word >>> shift + 36 & 0x1L;
            values[offset + 37 + valuesStart] = word >>> shift + 37 & 0x1L;
            values[offset + 38 + valuesStart] = word >>> shift + 38 & 0x1L;
            values[offset + 39 + valuesStart] = word >>> shift + 39 & 0x1L;
            values[offset + 40 + valuesStart] = word >>> shift + 40 & 0x1L;
            values[offset + 41 + valuesStart] = word >>> shift + 41 & 0x1L;
            values[offset + 42 + valuesStart] = word >>> shift + 42 & 0x1L;
            values[offset + 43 + valuesStart] = word >>> shift + 43 & 0x1L;
            values[offset + 44 + valuesStart] = word >>> shift + 44 & 0x1L;
            values[offset + 45 + valuesStart] = word >>> shift + 45 & 0x1L;
            values[offset + 46 + valuesStart] = word >>> shift + 46 & 0x1L;
            values[offset + 47 + valuesStart] = word >>> shift + 47 & 0x1L;
            values[offset + 48 + valuesStart] = word >>> shift + 48 & 0x1L;
            values[offset + 49 + valuesStart] = word >>> shift + 49 & 0x1L;
            values[offset + 50 + valuesStart] = word >>> shift + 50 & 0x1L;
            values[offset + 51 + valuesStart] = word >>> shift + 51 & 0x1L;
            values[offset + 52 + valuesStart] = word >>> shift + 52 & 0x1L;
            values[offset + 53 + valuesStart] = word >>> shift + 53 & 0x1L;
            values[offset + 54 + valuesStart] = word >>> shift + 54 & 0x1L;
            values[offset + 55 + valuesStart] = word >>> shift + 55 & 0x1L;
            values[offset + 56 + valuesStart] = word >>> shift + 56 & 0x1L;
            values[offset + 57 + valuesStart] = word >>> shift + 57 & 0x1L;
            values[offset + 58 + valuesStart] = word >>> shift + 58 & 0x1L;
            values[offset + 59 + valuesStart] = word >>> shift + 59 & 0x1L;
            values[offset + 60 + valuesStart] = word >>> shift + 60 & 0x1L;
            values[offset + 61 + valuesStart] = word >>> shift + 61 & 0x1L;
            values[offset + 62 + valuesStart] = word >>> shift + 62 & 0x1L;
            values[offset + 63 + valuesStart] = word >>> shift + 63 & 0x1L;
            shift += 63;
            if (i == words - 1) break;
            if (shift > 63) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 63 + valuesStart] |= word << shift & 0x1L;
                shift = 1 - shift;
                offset += 64;
            } else if (shift == 63) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 64;
            } else {
                shift += 1;
                values[offset + 64 + valuesStart] = word >>> shift & 0x1L;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 64 + valuesStart] |= word << shift & 0x1L;
                shift = 1 - shift;
                offset += 65;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 2-bit values.
     */
    private static long unpackLoop2(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 2, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3L;
            values[offset + 1 + valuesStart] = word >>> shift + 2 & 0x3L;
            values[offset + 2 + valuesStart] = word >>> shift + 4 & 0x3L;
            values[offset + 3 + valuesStart] = word >>> shift + 6 & 0x3L;
            values[offset + 4 + valuesStart] = word >>> shift + 8 & 0x3L;
            values[offset + 5 + valuesStart] = word >>> shift + 10 & 0x3L;
            values[offset + 6 + valuesStart] = word >>> shift + 12 & 0x3L;
            values[offset + 7 + valuesStart] = word >>> shift + 14 & 0x3L;
            values[offset + 8 + valuesStart] = word >>> shift + 16 & 0x3L;
            values[offset + 9 + valuesStart] = word >>> shift + 18 & 0x3L;
            values[offset + 10 + valuesStart] = word >>> shift + 20 & 0x3L;
            values[offset + 11 + valuesStart] = word >>> shift + 22 & 0x3L;
            values[offset + 12 + valuesStart] = word >>> shift + 24 & 0x3L;
            values[offset + 13 + valuesStart] = word >>> shift + 26 & 0x3L;
            values[offset + 14 + valuesStart] = word >>> shift + 28 & 0x3L;
            values[offset + 15 + valuesStart] = word >>> shift + 30 & 0x3L;
            values[offset + 16 + valuesStart] = word >>> shift + 32 & 0x3L;
            values[offset + 17 + valuesStart] = word >>> shift + 34 & 0x3L;
            values[offset + 18 + valuesStart] = word >>> shift + 36 & 0x3L;
            values[offset + 19 + valuesStart] = word >>> shift + 38 & 0x3L;
            values[offset + 20 + valuesStart] = word >>> shift + 40 & 0x3L;
            values[offset + 21 + valuesStart] = word >>> shift + 42 & 0x3L;
            values[offset + 22 + valuesStart] = word >>> shift + 44 & 0x3L;
            values[offset + 23 + valuesStart] = word >>> shift + 46 & 0x3L;
            values[offset + 24 + valuesStart] = word >>> shift + 48 & 0x3L;
            values[offset + 25 + valuesStart] = word >>> shift + 50 & 0x3L;
            values[offset + 26 + valuesStart] = word >>> shift + 52 & 0x3L;
            values[offset + 27 + valuesStart] = word >>> shift + 54 & 0x3L;
            values[offset + 28 + valuesStart] = word >>> shift + 56 & 0x3L;
            values[offset + 29 + valuesStart] = word >>> shift + 58 & 0x3L;
            values[offset + 30 + valuesStart] = word >>> shift + 60 & 0x3L;
            values[offset + 31 + valuesStart] = word >>> shift + 62 & 0x3L;
            shift += 62;
            if (i == words - 1) break;
            if (shift > 62) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 31 + valuesStart] |= word << shift & 0x3L;
                shift = 2 - shift;
                offset += 32;
            } else if (shift == 62) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 32;
            } else {
                shift += 2;
                values[offset + 32 + valuesStart] = word >>> shift & 0x3L;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 32 + valuesStart] |= word << shift & 0x3L;
                shift = 2 - shift;
                offset += 33;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 3-bit values.
     */
    private static long unpackLoop3(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 3, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7L;
            values[offset + 1 + valuesStart] = word >>> shift + 3 & 0x7L;
            values[offset + 2 + valuesStart] = word >>> shift + 6 & 0x7L;
            values[offset + 3 + valuesStart] = word >>> shift + 9 & 0x7L;
            values[offset + 4 + valuesStart] = word >>> shift + 12 & 0x7L;
            values[offset + 5 + valuesStart] = word >>> shift + 15 & 0x7L;
            values[offset + 6 + valuesStart] = word >>> shift + 18 & 0x7L;
            values[offset + 7 + valuesStart] = word >>> shift + 21 & 0x7L;
            values[offset + 8 + valuesStart] = word >>> shift + 24 & 0x7L;
            values[offset + 9 + valuesStart] = word >>> shift + 27 & 0x7L;
            values[offset + 10 + valuesStart] = word >>> shift + 30 & 0x7L;
            values[offset + 11 + valuesStart] = word >>> shift + 33 & 0x7L;
            values[offset + 12 + valuesStart] = word >>> shift + 36 & 0x7L;
            values[offset + 13 + valuesStart] = word >>> shift + 39 & 0x7L;
            values[offset + 14 + valuesStart] = word >>> shift + 42 & 0x7L;
            values[offset + 15 + valuesStart] = word >>> shift + 45 & 0x7L;
            values[offset + 16 + valuesStart] = word >>> shift + 48 & 0x7L;
            values[offset + 17 + valuesStart] = word >>> shift + 51 & 0x7L;
            values[offset + 18 + valuesStart] = word >>> shift + 54 & 0x7L;
            values[offset + 19 + valuesStart] = word >>> shift + 57 & 0x7L;
            values[offset + 20 + valuesStart] = word >>> shift + 60 & 0x7L;
            shift += 60;
            if (i == words - 1) break;
            if (shift > 61) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 20 + valuesStart] |= word << shift & 0x7L;
                shift = 3 - shift;
                offset += 21;
            } else if (shift == 61) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 21;
            } else {
                shift += 3;
                values[offset + 21 + valuesStart] = word >>> shift & 0x7L;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 21 + valuesStart] |= word << shift & 0x7L;
                shift = 3 - shift;
                offset += 22;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 4-bit values.
     */
    private static long unpackLoop4(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 4, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFL;
            values[offset + 1 + valuesStart] = word >>> shift + 4 & 0xFL;
            values[offset + 2 + valuesStart] = word >>> shift + 8 & 0xFL;
            values[offset + 3 + valuesStart] = word >>> shift + 12 & 0xFL;
            values[offset + 4 + valuesStart] = word >>> shift + 16 & 0xFL;
            values[offset + 5 + valuesStart] = word >>> shift + 20 & 0xFL;
            values[offset + 6 + valuesStart] = word >>> shift + 24 & 0xFL;
            values[offset + 7 + valuesStart] = word >>> shift + 28 & 0xFL;
            values[offset + 8 + valuesStart] = word >>> shift + 32 & 0xFL;
            values[offset + 9 + valuesStart] = word >>> shift + 36 & 0xFL;
            values[offset + 10 + valuesStart] = word >>> shift + 40 & 0xFL;
            values[offset + 11 + valuesStart] = word >>> shift + 44 & 0xFL;
            values[offset + 12 + valuesStart] = word >>> shift + 48 & 0xFL;
            values[offset + 13 + valuesStart] = word >>> shift + 52 & 0xFL;
            values[offset + 14 + valuesStart] = word >>> shift + 56 & 0xFL;
            values[offset + 15 + valuesStart] = word >>> shift + 60 & 0xFL;
            shift += 60;
            if (i == words - 1) break;
            if (shift > 60) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 15 + valuesStart] |= word << shift & 0xFL;
                shift = 4 - shift;
                offset += 16;
            } else if (shift == 60) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 16;
            } else {
                shift += 4;
                values[offset + 16 + valuesStart] = word >>> shift & 0xFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 16 + valuesStart] |= word << shift & 0xFL;
                shift = 4 - shift;
                offset += 17;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 5-bit values.
     */
    private static long unpackLoop5(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 5, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FL;
            values[offset + 1 + valuesStart] = word >>> shift + 5 & 0x1FL;
            values[offset + 2 + valuesStart] = word >>> shift + 10 & 0x1FL;
            values[offset + 3 + valuesStart] = word >>> shift + 15 & 0x1FL;
            values[offset + 4 + valuesStart] = word >>> shift + 20 & 0x1FL;
            values[offset + 5 + valuesStart] = word >>> shift + 25 & 0x1FL;
            values[offset + 6 + valuesStart] = word >>> shift + 30 & 0x1FL;
            values[offset + 7 + valuesStart] = word >>> shift + 35 & 0x1FL;
            values[offset + 8 + valuesStart] = word >>> shift + 40 & 0x1FL;
            values[offset + 9 + valuesStart] = word >>> shift + 45 & 0x1FL;
            values[offset + 10 + valuesStart] = word >>> shift + 50 & 0x1FL;
            values[offset + 11 + valuesStart] = word >>> shift + 55 & 0x1FL;
            shift += 55;
            if (i == words - 1) break;
            if (shift > 59) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 11 + valuesStart] |= word << shift & 0x1FL;
                shift = 5 - shift;
                offset += 12;
            } else if (shift == 59) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 12;
            } else {
                shift += 5;
                values[offset + 12 + valuesStart] = word >>> shift & 0x1FL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 12 + valuesStart] |= word << shift & 0x1FL;
                shift = 5 - shift;
                offset += 13;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 6-bit values.
     */
    private static long unpackLoop6(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 6, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FL;
            values[offset + 1 + valuesStart] = word >>> shift + 6 & 0x3FL;
            values[offset + 2 + valuesStart] = word >>> shift + 12 & 0x3FL;
            values[offset + 3 + valuesStart] = word >>> shift + 18 & 0x3FL;
            values[offset + 4 + valuesStart] = word >>> shift + 24 & 0x3FL;
            values[offset + 5 + valuesStart] = word >>> shift + 30 & 0x3FL;
            values[offset + 6 + valuesStart] = word >>> shift + 36 & 0x3FL;
            values[offset + 7 + valuesStart] = word >>> shift + 42 & 0x3FL;
            values[offset + 8 + valuesStart] = word >>> shift + 48 & 0x3FL;
            values[offset + 9 + valuesStart] = word >>> shift + 54 & 0x3FL;
            shift += 54;
            if (i == words - 1) break;
            if (shift > 58) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 9 + valuesStart] |= word << shift & 0x3FL;
                shift = 6 - shift;
                offset += 10;
            } else if (shift == 58) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 10;
            } else {
                shift += 6;
                values[offset + 10 + valuesStart] = word >>> shift & 0x3FL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 10 + valuesStart] |= word << shift & 0x3FL;
                shift = 6 - shift;
                offset += 11;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 7-bit values.
     */
    private static long unpackLoop7(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 7, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FL;
            values[offset + 1 + valuesStart] = word >>> shift + 7 & 0x7FL;
            values[offset + 2 + valuesStart] = word >>> shift + 14 & 0x7FL;
            values[offset + 3 + valuesStart] = word >>> shift + 21 & 0x7FL;
            values[offset + 4 + valuesStart] = word >>> shift + 28 & 0x7FL;
            values[offset + 5 + valuesStart] = word >>> shift + 35 & 0x7FL;
            values[offset + 6 + valuesStart] = word >>> shift + 42 & 0x7FL;
            values[offset + 7 + valuesStart] = word >>> shift + 49 & 0x7FL;
            values[offset + 8 + valuesStart] = word >>> shift + 56 & 0x7FL;
            shift += 56;
            if (i == words - 1) break;
            if (shift > 57) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 8 + valuesStart] |= word << shift & 0x7FL;
                shift = 7 - shift;
                offset += 9;
            } else if (shift == 57) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 9;
            } else {
                shift += 7;
                values[offset + 9 + valuesStart] = word >>> shift & 0x7FL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 9 + valuesStart] |= word << shift & 0x7FL;
                shift = 7 - shift;
                offset += 10;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 8-bit values.
     */
    private static long unpackLoop8(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 8, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 8 & 0xFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 16 & 0xFFL;
            values[offset + 3 + valuesStart] = word >>> shift + 24 & 0xFFL;
            values[offset + 4 + valuesStart] = word >>> shift + 32 & 0xFFL;
            values[offset + 5 + valuesStart] = word >>> shift + 40 & 0xFFL;
            values[offset + 6 + valuesStart] = word >>> shift + 48 & 0xFFL;
            values[offset + 7 + valuesStart] = word >>> shift + 56 & 0xFFL;
            shift += 56;
            if (i == words - 1) break;
            if (shift > 56) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 7 + valuesStart] |= word << shift & 0xFFL;
                shift = 8 - shift;
                offset += 8;
            } else if (shift == 56) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 8;
            } else {
                shift += 8;
                values[offset + 8 + valuesStart] = word >>> shift & 0xFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 8 + valuesStart] |= word << shift & 0xFFL;
                shift = 8 - shift;
                offset += 9;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 9-bit values.
     */
    private static long unpackLoop9(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 9, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFL;
            values[offset + 1 + valuesStart] = word >>> shift + 9 & 0x1FFL;
            values[offset + 2 + valuesStart] = word >>> shift + 18 & 0x1FFL;
            values[offset + 3 + valuesStart] = word >>> shift + 27 & 0x1FFL;
            values[offset + 4 + valuesStart] = word >>> shift + 36 & 0x1FFL;
            values[offset + 5 + valuesStart] = word >>> shift + 45 & 0x1FFL;
            values[offset + 6 + valuesStart] = word >>> shift + 54 & 0x1FFL;
            shift += 54;
            if (i == words - 1) break;
            if (shift > 55) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 6 + valuesStart] |= word << shift & 0x1FFL;
                shift = 9 - shift;
                offset += 7;
            } else if (shift == 55) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 7;
            } else {
                shift += 9;
                values[offset + 7 + valuesStart] = word >>> shift & 0x1FFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 7 + valuesStart] |= word << shift & 0x1FFL;
                shift = 9 - shift;
                offset += 8;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 10-bit values.
     */
    private static long unpackLoop10(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 10, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFL;
            values[offset + 1 + valuesStart] = word >>> shift + 10 & 0x3FFL;
            values[offset + 2 + valuesStart] = word >>> shift + 20 & 0x3FFL;
            values[offset + 3 + valuesStart] = word >>> shift + 30 & 0x3FFL;
            values[offset + 4 + valuesStart] = word >>> shift + 40 & 0x3FFL;
            values[offset + 5 + valuesStart] = word >>> shift + 50 & 0x3FFL;
            shift += 50;
            if (i == words - 1) break;
            if (shift > 54) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 5 + valuesStart] |= word << shift & 0x3FFL;
                shift = 10 - shift;
                offset += 6;
            } else if (shift == 54) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 6;
            } else {
                shift += 10;
                values[offset + 6 + valuesStart] = word >>> shift & 0x3FFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 6 + valuesStart] |= word << shift & 0x3FFL;
                shift = 10 - shift;
                offset += 7;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 11-bit values.
     */
    private static long unpackLoop11(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 11, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFL;
            values[offset + 1 + valuesStart] = word >>> shift + 11 & 0x7FFL;
            values[offset + 2 + valuesStart] = word >>> shift + 22 & 0x7FFL;
            values[offset + 3 + valuesStart] = word >>> shift + 33 & 0x7FFL;
            values[offset + 4 + valuesStart] = word >>> shift + 44 & 0x7FFL;
            shift += 44;
            if (i == words - 1) break;
            if (shift > 53) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 4 + valuesStart] |= word << shift & 0x7FFL;
                shift = 11 - shift;
                offset += 5;
            } else if (shift == 53) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 5;
            } else {
                shift += 11;
                values[offset + 5 + valuesStart] = word >>> shift & 0x7FFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 5 + valuesStart] |= word << shift & 0x7FFL;
                shift = 11 - shift;
                offset += 6;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 12-bit values.
     */
    private static long unpackLoop12(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 12, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 12 & 0xFFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 24 & 0xFFFL;
            values[offset + 3 + valuesStart] = word >>> shift + 36 & 0xFFFL;
            values[offset + 4 + valuesStart] = word >>> shift + 48 & 0xFFFL;
            shift += 48;
            if (i == words - 1) break;
            if (shift > 52) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 4 + valuesStart] |= word << shift & 0xFFFL;
                shift = 12 - shift;
                offset += 5;
            } else if (shift == 52) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 5;
            } else {
                shift += 12;
                values[offset + 5 + valuesStart] = word >>> shift & 0xFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 5 + valuesStart] |= word << shift & 0xFFFL;
                shift = 12 - shift;
                offset += 6;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 13-bit values.
     */
    private static long unpackLoop13(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 13, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 13 & 0x1FFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 26 & 0x1FFFL;
            values[offset + 3 + valuesStart] = word >>> shift + 39 & 0x1FFFL;
            shift += 39;
            if (i == words - 1) break;
            if (shift > 51) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 3 + valuesStart] |= word << shift & 0x1FFFL;
                shift = 13 - shift;
                offset += 4;
            } else if (shift == 51) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 4;
            } else {
                shift += 13;
                values[offset + 4 + valuesStart] = word >>> shift & 0x1FFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 4 + valuesStart] |= word << shift & 0x1FFFL;
                shift = 13 - shift;
                offset += 5;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 14-bit values.
     */
    private static long unpackLoop14(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 14, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 14 & 0x3FFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 28 & 0x3FFFL;
            values[offset + 3 + valuesStart] = word >>> shift + 42 & 0x3FFFL;
            shift += 42;
            if (i == words - 1) break;
            if (shift > 50) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 3 + valuesStart] |= word << shift & 0x3FFFL;
                shift = 14 - shift;
                offset += 4;
            } else if (shift == 50) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 4;
            } else {
                shift += 14;
                values[offset + 4 + valuesStart] = word >>> shift & 0x3FFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 4 + valuesStart] |= word << shift & 0x3FFFL;
                shift = 14 - shift;
                offset += 5;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 15-bit values.
     */
    private static long unpackLoop15(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 15, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 15 & 0x7FFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 30 & 0x7FFFL;
            values[offset + 3 + valuesStart] = word >>> shift + 45 & 0x7FFFL;
            shift += 45;
            if (i == words - 1) break;
            if (shift > 49) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 3 + valuesStart] |= word << shift & 0x7FFFL;
                shift = 15 - shift;
                offset += 4;
            } else if (shift == 49) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 4;
            } else {
                shift += 15;
                values[offset + 4 + valuesStart] = word >>> shift & 0x7FFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 4 + valuesStart] |= word << shift & 0x7FFFL;
                shift = 15 - shift;
                offset += 5;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 16-bit values.
     */
    private static long unpackLoop16(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 16, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 16 & 0xFFFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 32 & 0xFFFFL;
            values[offset + 3 + valuesStart] = word >>> shift + 48 & 0xFFFFL;
            shift += 48;
            if (i == words - 1) break;
            if (shift > 48) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 3 + valuesStart] |= word << shift & 0xFFFFL;
                shift = 16 - shift;
                offset += 4;
            } else if (shift == 48) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 4;
            } else {
                shift += 16;
                values[offset + 4 + valuesStart] = word >>> shift & 0xFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 4 + valuesStart] |= word << shift & 0xFFFFL;
                shift = 16 - shift;
                offset += 5;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 17-bit values.
     */
    private static long unpackLoop17(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 17, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 17 & 0x1FFFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 34 & 0x1FFFFL;
            shift += 34;
            if (i == words - 1) break;
            if (shift > 47) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x1FFFFL;
                shift = 17 - shift;
                offset += 3;
            } else if (shift == 47) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 3;
            } else {
                shift += 17;
                values[offset + 3 + valuesStart] = word >>> shift & 0x1FFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 3 + valuesStart] |= word << shift & 0x1FFFFL;
                shift = 17 - shift;
                offset += 4;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 18-bit values.
     */
    private static long unpackLoop18(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 18, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 18 & 0x3FFFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 36 & 0x3FFFFL;
            shift += 36;
            if (i == words - 1) break;
            if (shift > 46) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x3FFFFL;
                shift = 18 - shift;
                offset += 3;
            } else if (shift == 46) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 3;
            } else {
                shift += 18;
                values[offset + 3 + valuesStart] = word >>> shift & 0x3FFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 3 + valuesStart] |= word << shift & 0x3FFFFL;
                shift = 18 - shift;
                offset += 4;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 19-bit values.
     */
    private static long unpackLoop19(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 19, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 19 & 0x7FFFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 38 & 0x7FFFFL;
            shift += 38;
            if (i == words - 1) break;
            if (shift > 45) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x7FFFFL;
                shift = 19 - shift;
                offset += 3;
            } else if (shift == 45) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 3;
            } else {
                shift += 19;
                values[offset + 3 + valuesStart] = word >>> shift & 0x7FFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 3 + valuesStart] |= word << shift & 0x7FFFFL;
                shift = 19 - shift;
                offset += 4;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 20-bit values.
     */
    private static long unpackLoop20(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 20, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 20 & 0xFFFFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 40 & 0xFFFFFL;
            shift += 40;
            if (i == words - 1) break;
            if (shift > 44) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0xFFFFFL;
                shift = 20 - shift;
                offset += 3;
            } else if (shift == 44) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 3;
            } else {
                shift += 20;
                values[offset + 3 + valuesStart] = word >>> shift & 0xFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 3 + valuesStart] |= word << shift & 0xFFFFFL;
                shift = 20 - shift;
                offset += 4;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 21-bit values.
     */
    private static long unpackLoop21(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 21, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 21 & 0x1FFFFFL;
            values[offset + 2 + valuesStart] = word >>> shift + 42 & 0x1FFFFFL;
            shift += 42;
            if (i == words - 1) break;
            if (shift > 43) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x1FFFFFL;
                shift = 21 - shift;
                offset += 3;
            } else if (shift == 43) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 3;
            } else {
                shift += 21;
                values[offset + 3 + valuesStart] = word >>> shift & 0x1FFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 3 + valuesStart] |= word << shift & 0x1FFFFFL;
                shift = 21 - shift;
                offset += 4;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 22-bit values.
     */
    private static long unpackLoop22(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 22, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 22 & 0x3FFFFFL;
            shift += 22;
            if (i == words - 1) break;
            if (shift > 42) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFL;
                shift = 22 - shift;
                offset += 2;
            } else if (shift == 42) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 22;
                values[offset + 2 + valuesStart] = word >>> shift & 0x3FFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x3FFFFFL;
                shift = 22 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 23-bit values.
     */
    private static long unpackLoop23(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 23, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 23 & 0x7FFFFFL;
            shift += 23;
            if (i == words - 1) break;
            if (shift > 41) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFL;
                shift = 23 - shift;
                offset += 2;
            } else if (shift == 41) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 23;
                values[offset + 2 + valuesStart] = word >>> shift & 0x7FFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x7FFFFFL;
                shift = 23 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 24-bit values.
     */
    private static long unpackLoop24(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 24, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 24 & 0xFFFFFFL;
            shift += 24;
            if (i == words - 1) break;
            if (shift > 40) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFL;
                shift = 24 - shift;
                offset += 2;
            } else if (shift == 40) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 24;
                values[offset + 2 + valuesStart] = word >>> shift & 0xFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0xFFFFFFL;
                shift = 24 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 25-bit values.
     */
    private static long unpackLoop25(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 25, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 25 & 0x1FFFFFFL;
            shift += 25;
            if (i == words - 1) break;
            if (shift > 39) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFL;
                shift = 25 - shift;
                offset += 2;
            } else if (shift == 39) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 25;
                values[offset + 2 + valuesStart] = word >>> shift & 0x1FFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x1FFFFFFL;
                shift = 25 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 26-bit values.
     */
    private static long unpackLoop26(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 26, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 26 & 0x3FFFFFFL;
            shift += 26;
            if (i == words - 1) break;
            if (shift > 38) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFL;
                shift = 26 - shift;
                offset += 2;
            } else if (shift == 38) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 26;
                values[offset + 2 + valuesStart] = word >>> shift & 0x3FFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x3FFFFFFL;
                shift = 26 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 27-bit values.
     */
    private static long unpackLoop27(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 27, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 27 & 0x7FFFFFFL;
            shift += 27;
            if (i == words - 1) break;
            if (shift > 37) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFL;
                shift = 27 - shift;
                offset += 2;
            } else if (shift == 37) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 27;
                values[offset + 2 + valuesStart] = word >>> shift & 0x7FFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x7FFFFFFL;
                shift = 27 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 28-bit values.
     */
    private static long unpackLoop28(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 28, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 28 & 0xFFFFFFFL;
            shift += 28;
            if (i == words - 1) break;
            if (shift > 36) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFFL;
                shift = 28 - shift;
                offset += 2;
            } else if (shift == 36) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 28;
                values[offset + 2 + valuesStart] = word >>> shift & 0xFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0xFFFFFFFL;
                shift = 28 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 29-bit values.
     */
    private static long unpackLoop29(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 29, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 29 & 0x1FFFFFFFL;
            shift += 29;
            if (i == words - 1) break;
            if (shift > 35) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFFL;
                shift = 29 - shift;
                offset += 2;
            } else if (shift == 35) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 29;
                values[offset + 2 + valuesStart] = word >>> shift & 0x1FFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x1FFFFFFFL;
                shift = 29 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 30-bit values.
     */
    private static long unpackLoop30(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 30, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 30 & 0x3FFFFFFFL;
            shift += 30;
            if (i == words - 1) break;
            if (shift > 34) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFFL;
                shift = 30 - shift;
                offset += 2;
            } else if (shift == 34) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 30;
                values[offset + 2 + valuesStart] = word >>> shift & 0x3FFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x3FFFFFFFL;
                shift = 30 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 31-bit values.
     */
    private static long unpackLoop31(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 31, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 31 & 0x7FFFFFFFL;
            shift += 31;
            if (i == words - 1) break;
            if (shift > 33) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFFL;
                shift = 31 - shift;
                offset += 2;
            } else if (shift == 33) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 31;
                values[offset + 2 + valuesStart] = word >>> shift & 0x7FFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0x7FFFFFFFL;
                shift = 31 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 32-bit values.
     */
    private static long unpackLoop32(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 32, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFFFL;
            values[offset + 1 + valuesStart] = word >>> shift + 32 & 0xFFFFFFFFL;
            shift += 32;
            if (i == words - 1) break;
            if (shift > 32) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFFFL;
                shift = 32 - shift;
                offset += 2;
            } else if (shift == 32) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 2;
            } else {
                shift += 32;
                values[offset + 2 + valuesStart] = word >>> shift & 0xFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 2 + valuesStart] |= word << shift & 0xFFFFFFFFL;
                shift = 32 - shift;
                offset += 3;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 33-bit values.
     */
    private static long unpackLoop33(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 33, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 31) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x1FFFFFFFFL;
                shift = 33 - shift;
                offset += 1;
            } else if (shift == 31) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 33;
                values[offset + 1 + valuesStart] = word >>> shift & 0x1FFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFFFL;
                shift = 33 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 34-bit values.
     */
    private static long unpackLoop34(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 34, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 30) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x3FFFFFFFFL;
                shift = 34 - shift;
                offset += 1;
            } else if (shift == 30) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 34;
                values[offset + 1 + valuesStart] = word >>> shift & 0x3FFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFFFL;
                shift = 34 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 35-bit values.
     */
    private static long unpackLoop35(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 35, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 29) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x7FFFFFFFFL;
                shift = 35 - shift;
                offset += 1;
            } else if (shift == 29) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 35;
                values[offset + 1 + valuesStart] = word >>> shift & 0x7FFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFFFL;
                shift = 35 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 36-bit values.
     */
    private static long unpackLoop36(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 36, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 28) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0xFFFFFFFFFL;
                shift = 36 - shift;
                offset += 1;
            } else if (shift == 28) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 36;
                values[offset + 1 + valuesStart] = word >>> shift & 0xFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFFFFL;
                shift = 36 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 37-bit values.
     */
    private static long unpackLoop37(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 37, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 27) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x1FFFFFFFFFL;
                shift = 37 - shift;
                offset += 1;
            } else if (shift == 27) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 37;
                values[offset + 1 + valuesStart] = word >>> shift & 0x1FFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFFFFL;
                shift = 37 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 38-bit values.
     */
    private static long unpackLoop38(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 38, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 26) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x3FFFFFFFFFL;
                shift = 38 - shift;
                offset += 1;
            } else if (shift == 26) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 38;
                values[offset + 1 + valuesStart] = word >>> shift & 0x3FFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFFFFL;
                shift = 38 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 39-bit values.
     */
    private static long unpackLoop39(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 39, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 25) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x7FFFFFFFFFL;
                shift = 39 - shift;
                offset += 1;
            } else if (shift == 25) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 39;
                values[offset + 1 + valuesStart] = word >>> shift & 0x7FFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFFFFL;
                shift = 39 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 40-bit values.
     */
    private static long unpackLoop40(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 40, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 24) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0xFFFFFFFFFFL;
                shift = 40 - shift;
                offset += 1;
            } else if (shift == 24) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 40;
                values[offset + 1 + valuesStart] = word >>> shift & 0xFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFFFFFL;
                shift = 40 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 41-bit values.
     */
    private static long unpackLoop41(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 41, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 23) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x1FFFFFFFFFFL;
                shift = 41 - shift;
                offset += 1;
            } else if (shift == 23) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 41;
                values[offset + 1 + valuesStart] = word >>> shift & 0x1FFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFFFFFL;
                shift = 41 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 42-bit values.
     */
    private static long unpackLoop42(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 42, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 22) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x3FFFFFFFFFFL;
                shift = 42 - shift;
                offset += 1;
            } else if (shift == 22) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 42;
                values[offset + 1 + valuesStart] = word >>> shift & 0x3FFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFFFFFL;
                shift = 42 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 43-bit values.
     */
    private static long unpackLoop43(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 43, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 21) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x7FFFFFFFFFFL;
                shift = 43 - shift;
                offset += 1;
            } else if (shift == 21) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 43;
                values[offset + 1 + valuesStart] = word >>> shift & 0x7FFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFFFFFL;
                shift = 43 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 44-bit values.
     */
    private static long unpackLoop44(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 44, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 20) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0xFFFFFFFFFFFL;
                shift = 44 - shift;
                offset += 1;
            } else if (shift == 20) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 44;
                values[offset + 1 + valuesStart] = word >>> shift & 0xFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFFFFFFL;
                shift = 44 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 45-bit values.
     */
    private static long unpackLoop45(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 45, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 19) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x1FFFFFFFFFFFL;
                shift = 45 - shift;
                offset += 1;
            } else if (shift == 19) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 45;
                values[offset + 1 + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFFFFFFL;
                shift = 45 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 46-bit values.
     */
    private static long unpackLoop46(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 46, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 18) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x3FFFFFFFFFFFL;
                shift = 46 - shift;
                offset += 1;
            } else if (shift == 18) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 46;
                values[offset + 1 + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFFFFFFL;
                shift = 46 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 47-bit values.
     */
    private static long unpackLoop47(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 47, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 17) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x7FFFFFFFFFFFL;
                shift = 47 - shift;
                offset += 1;
            } else if (shift == 17) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 47;
                values[offset + 1 + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFFFFFFL;
                shift = 47 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 48-bit values.
     */
    private static long unpackLoop48(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 48, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 16) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0xFFFFFFFFFFFFL;
                shift = 48 - shift;
                offset += 1;
            } else if (shift == 16) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 48;
                values[offset + 1 + valuesStart] = word >>> shift & 0xFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFFFFFFFL;
                shift = 48 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 49-bit values.
     */
    private static long unpackLoop49(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 49, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 15) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x1FFFFFFFFFFFFL;
                shift = 49 - shift;
                offset += 1;
            } else if (shift == 15) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 49;
                values[offset + 1 + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFFFFFFFL;
                shift = 49 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 50-bit values.
     */
    private static long unpackLoop50(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 50, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 14) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x3FFFFFFFFFFFFL;
                shift = 50 - shift;
                offset += 1;
            } else if (shift == 14) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 50;
                values[offset + 1 + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFFFFFFFL;
                shift = 50 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 51-bit values.
     */
    private static long unpackLoop51(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 51, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 13) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x7FFFFFFFFFFFFL;
                shift = 51 - shift;
                offset += 1;
            } else if (shift == 13) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 51;
                values[offset + 1 + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFFFFFFFL;
                shift = 51 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 52-bit values.
     */
    private static long unpackLoop52(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 52, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 12) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0xFFFFFFFFFFFFFL;
                shift = 52 - shift;
                offset += 1;
            } else if (shift == 12) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 52;
                values[offset + 1 + valuesStart] = word >>> shift & 0xFFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFFFFFFFFL;
                shift = 52 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 53-bit values.
     */
    private static long unpackLoop53(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 53, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 11) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x1FFFFFFFFFFFFFL;
                shift = 53 - shift;
                offset += 1;
            } else if (shift == 11) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 53;
                values[offset + 1 + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFFFFFFFFL;
                shift = 53 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 54-bit values.
     */
    private static long unpackLoop54(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 54, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 10) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x3FFFFFFFFFFFFFL;
                shift = 54 - shift;
                offset += 1;
            } else if (shift == 10) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 54;
                values[offset + 1 + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFFFFFFFFL;
                shift = 54 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 55-bit values.
     */
    private static long unpackLoop55(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 55, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 9) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x7FFFFFFFFFFFFFL;
                shift = 55 - shift;
                offset += 1;
            } else if (shift == 9) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 55;
                values[offset + 1 + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFFFFFFFFL;
                shift = 55 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 56-bit values.
     */
    private static long unpackLoop56(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 56, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 8) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0xFFFFFFFFFFFFFFL;
                shift = 56 - shift;
                offset += 1;
            } else if (shift == 8) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 56;
                values[offset + 1 + valuesStart] = word >>> shift & 0xFFFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFFFFFFFFFL;
                shift = 56 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 57-bit values.
     */
    private static long unpackLoop57(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 57, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 7) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x1FFFFFFFFFFFFFFL;
                shift = 57 - shift;
                offset += 1;
            } else if (shift == 7) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 57;
                values[offset + 1 + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFFFFFFFFFL;
                shift = 57 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 58-bit values.
     */
    private static long unpackLoop58(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 58, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 6) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x3FFFFFFFFFFFFFFL;
                shift = 58 - shift;
                offset += 1;
            } else if (shift == 6) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 58;
                values[offset + 1 + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFFFFFFFFFL;
                shift = 58 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 59-bit values.
     */
    private static long unpackLoop59(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 59, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 5) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x7FFFFFFFFFFFFFFL;
                shift = 59 - shift;
                offset += 1;
            } else if (shift == 5) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 59;
                values[offset + 1 + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFFFFFFFFFL;
                shift = 59 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 60-bit values.
     */
    private static long unpackLoop60(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 60, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0xFFFFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 4) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0xFFFFFFFFFFFFFFFL;
                shift = 60 - shift;
                offset += 1;
            } else if (shift == 4) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 60;
                values[offset + 1 + valuesStart] = word >>> shift & 0xFFFFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0xFFFFFFFFFFFFFFFL;
                shift = 60 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 61-bit values.
     */
    private static long unpackLoop61(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 61, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 3) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x1FFFFFFFFFFFFFFFL;
                shift = 61 - shift;
                offset += 1;
            } else if (shift == 3) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 61;
                values[offset + 1 + valuesStart] = word >>> shift & 0x1FFFFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x1FFFFFFFFFFFFFFFL;
                shift = 61 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 62-bit values.
     */
    private static long unpackLoop62(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 62, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 2) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x3FFFFFFFFFFFFFFFL;
                shift = 62 - shift;
                offset += 1;
            } else if (shift == 2) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 62;
                values[offset + 1 + valuesStart] = word >>> shift & 0x3FFFFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x3FFFFFFFFFFFFFFFL;
                shift = 62 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 63-bit values.
     */
    private static long unpackLoop63(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 63, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFFFFFL;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 1) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift & 0x7FFFFFFFFFFFFFFFL;
                shift = 63 - shift;
                offset += 1;
            } else if (shift == 1) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 63;
                values[offset + 1 + valuesStart] = word >>> shift & 0x7FFFFFFFFFFFFFFFL;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift & 0x7FFFFFFFFFFFFFFFL;
                shift = 63 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }

    /**
     * Unpacks `valuesLength` 64-bit values.
     */
    private static long unpackLoop64(long[] values, int valuesStart, int valuesLength, long packedPtr) {
        int words = BitUtil.ceilDiv(valuesLength * 64, 64);
        int shift = 0;
        int offset = 0;
        long word = UnsafeUtil.getLong(packedPtr);
        packedPtr += 8;
        for (int i = 0; i < words; i += 1) {
            values[offset + valuesStart] = word >>> shift;
            shift += 0;
            if (i == words - 1) break;
            if (shift > 0) {
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + valuesStart] |= word << shift;
                shift = 64 - shift;
                offset += 1;
            } else if (shift == 0) {
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                shift = 0;
                offset += 1;
            } else {
                shift += 64;
                values[offset + 1 + valuesStart] = word >>> shift;
                shift = 64 - shift;
                word = UnsafeUtil.getLong(packedPtr);
                packedPtr += 8;
                values[offset + 1 + valuesStart] |= word << shift;
                shift = 64 - shift;
                offset += 2;
            }
        }
        return packedPtr;
    }
}
